问题描述
我正在为一个乐队制作出勤登记表.我的想法是在表格的一部分中输入用于表演或排练的活动信息.这是事件表的模型:
I'm working on an attendance entry form for a band. My idea is to have a section of the form to enter event information for a performance or rehearsal. Here's the model for the event table:
class Event(models.Model):
event_id = models.AutoField(primary_key=True)
date = models.DateField()
event_type = models.ForeignKey(EventType)
description = models.TextField()
然后我想要一个内联的 FormSet,将乐队成员链接到活动并记录他们是否出席、缺席或请假:
Then I'd like to have an inline FormSet that links the band members to the event and records whether they were present, absent, or excused:
class Attendance(models.Model):
attendance_id = models.AutoField(primary_key=True)
event_id = models.ForeignKey(Event)
member_id = models.ForeignKey(Member)
attendance_type = models.ForeignKey(AttendanceType)
comment = models.TextField(blank=True)
现在,我想要做的是用所有当前成员的条目预先填充这个内联 FormSet,并将它们默认为存在(大约 60 个成员).不幸的是,Django 在这种情况下不允许使用初始值.
Now, what I'd like to do is to pre-populate this inline FormSet with entries for all the current members and default them to being present (around 60 members). Unfortunately, Django doesn't allow initial values in this case.
有什么建议吗?
推荐答案
所以,你不会喜欢这个答案,部分原因是我还没有完成代码的编写,部分原因是工作量很大.
So, you're not going to like the answer, partly because I'm not yet done writing the code and partly because it's a lot of work.
当我自己遇到这个问题时我发现,你需要做的是:
What you need to do, as I discovered when I ran into this myself, is:
- 花大量时间阅读 formset 和 model-formset 代码,以了解它们是如何工作的(有些功能存在于 formset 类中,而有些功能存在于工厂中,这一事实对此没有帮助将它们吐出的函数).您将在后面的步骤中需要这些知识.
- 编写您自己的表单集类,该类继承自
BaseInlineFormSet
并接受initial
.这里真正棘手的一点是你必须覆盖__init__()
,并且你必须确保它调用BaseFormSet.__init__()
而不是使用直接的父或祖父__init__()
(因为它们分别是BaseInlineFormSet
和BaseModelFormSet
,并且它们都不能处理初始数据). - 编写您自己的适当管理内联类的子类(在我的例子中是
TabularInline
)并覆盖它的get_formset
方法以返回inlineformset_factory()
使用您的自定义表单集类. - 在具有内联模型的实际
ModelAdmin
子类上,覆盖add_view
和change_view
,并复制大部分代码,但使用一个重大变化:构建您的表单集需要的初始数据,并将其传递给您的自定义表单集(将由您的ModelAdmin
的get_formsets()
方法返回).
- Spend a lot of time reading through the formset and model-formset code to get a feel for how it all works (not helped by the fact that some of the functionality lives on the formset classes, and some of it lives in factory functions which spit them out). You will need this knowledge in the later steps.
- Write your own formset class which subclasses from
BaseInlineFormSet
and acceptsinitial
. The really tricky bit here is that you must override__init__()
, and you must make sure that it calls up toBaseFormSet.__init__()
rather than using the direct parent or grandparent__init__()
(since those areBaseInlineFormSet
andBaseModelFormSet
, respectively, and neither of them can handle initial data). - Write your own subclass of the appropriate admin inline class (in my case it was
TabularInline
) and override itsget_formset
method to return the result ofinlineformset_factory()
using your custom formset class. - On the actual
ModelAdmin
subclass for the model with the inline, overrideadd_view
andchange_view
, and replicate most of the code, but with one big change: build the initial data your formset will need, and pass it to your custom formset (which will be returned by yourModelAdmin
'sget_formsets()
method).
我与 Brian 和 Joseph 就在未来的 Django 版本中改进这一点进行了一些富有成效的交谈;目前,模型表单集的工作方式只会让这比通常更麻烦,但通过一些 API 清理,我认为它可以变得非常简单.
I've had a few productive chats with Brian and Joseph about improving this for future Django releases; at the moment, the way the model formsets work just make this more trouble than it's usually worth, but with a bit of API cleanup I think it could be made extremely easy.
这篇关于预填充内联 FormSet?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!