预先填入内联FormSet? [英] Pre-populate an inline FormSet?
问题描述
class Event(models.Model):
/ pre>
event_id = models.AutoField( primary_key = True)
date = models.DateField()
event_type = models.ForeignKey(EventType)
description = models.TextField()
然后,我想有一个内联FormSet,将乐队成员链接到活动,并记录他们是否在场,缺席或被拒绝:
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 在这种情况下不允许初始值。
任何建议?
解决方案所以,你不是就像答案一样,部分是因为我还没有编写代码,部分是因为它的工作很多。
我发现你需要做什么当我遇到这个问题时,是:
- 花费大量时间阅读表单和模型表单代码,以获得感觉这一切如何工作(没有一些功能生活在formset类上,其中一些功能生活在工厂功能中,它们会吐出来)。您将在后面的步骤中需要这些知识。
- 编写自己的formset类,从
BaseInlineFormSet
子类中接受初始
。这里真的很棘手的一点是,你必须覆盖__ init __()
,你必须确保它调用到BaseFormSet .__ init __()
,而不是使用直接父或祖父母__ init __()
(因为那些是$ $ c> BaseInlineFormSet 和BaseModelFormSet
,它们都不能处理初始数据)。
- 编写自己的子类的适当的管理内联类(在我的情况下,它是
TabularInline
),并将其get_formset
方法覆盖使用您的自定义表单类返回inlineformset_factory()
的结果。
- 在实际的
ModelAdmin
具有内联模型的子类,覆盖add_view
和change_view
,并复制大部分代码,但是有一个很大的变化:构建您的formset将需要的初始数据,并将其传递给您的自定义表单集(将由您的ModelAdmin
的get_formsets()
方法)。
我与Brian和Joseph进行了几次生产性聊天,为未来的Django版本改进了这一点;目前,模型表单的工作方式只是使这种情况比通常值得的更麻烦,但是通过一些API清理,我认为这可以非常容易。
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()
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)
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.
Any suggestions?
解决方案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:
- 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).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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!