【问题标题】:Accessing django formset data访问 django formset 数据
【发布时间】:2012-06-26 09:35:03
【问题描述】:

我在 django 中有一个表单集,它使用具有一对多关系的模型。许多与会者可以参加一个活动。

我正在表单集中发送模型的“许多”部分。问题是返回的数据没有设置主键。由于未设置表单集主键数据,因此出现验证错误。

在我看来,我知道主键应该是什么。我想在验证之前设置它。在我发送表单以供显示之前设置值或设置值。但我不知道如何在formset数据中设置。

在下面的代码中,外键是event

选项1:在显示表单之前设置外键:

#models.py  - note 2 foreign keys
class Attendee(models.Model):
    event = models.ForeignKey(Event)
    sponsor = models.ForeignKey(Customer)
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30) 

# forms.py
class AttendeeForm(forms.ModelForm): 
  event = forms.IntegerField(required=True, widget=forms.HiddenInput()) 

  class Meta: 
    model = Attendee 
    fields = ( 'last_name', 'first_name', ) 
    exclude = ('event', )  # excluded so user can't set foreign key

# views.py
event = get_object_or_404(Event, id=event_id)
AttendeeFormSet = inlineformset_factory(Event, Attendee, form=AttendeeForm, extra=1)
formset = AttendeeFormSet(instance=event, prefix='attendees')
# Error on form submit:  
#  Returns and redisplays the form along with message.
#  (Hidden field event) The inline foreign key did not match the parent instance primary key.


#  I also tried:  
#AttendeeFormSet = inlineformset_factory(Event, Customer, Attendee, form=AttendeeForm, extra=1)
# which gave error: 
# inlineformset_factory() got multiple values for keyword argument 'form'

选项 2:在返回 POST 上设置外键。请注意,即使存在数据,表单也无效,因为未设置外键。

formset = AttendeeFormSet(request.POST, request.FILES, prefix='attendees')
i=0
for form in formset.forms:
   # How can I set the foreign key (event) field here?
   pdb.set_trace()

if formset.is_valid():
   attendees = formset.save_all()


(Pdb) p form.fields
{'last_name': <django.forms.fields.CharField object at 0xaa44a2c>, 
'first_name':    <django.forms.fields.CharField object at 0xaa449ec>,  
'event': <django.forms.fields.IntegerField object at 0xaa44fec>}
(Pdb) 

在我的表单集中解决我的外键问题的最佳方法是什么? If Option 2 测试is_valid之前如何设置这个字段?

【问题讨论】:

标签: django django-forms


【解决方案1】:

由于这是一个表示外键关系的表单集,您应该使用inlineformset_factory 来构造该类。这将为您设置 FK:

AttendeeFormSet = formset_factory(Event, Attendee, form=AttendeeForm)
...
formset = AttendeeFormSet(instance=my_event)

【讨论】:

  • 我认为这是最接近成功的方式。但它仍然不能正常工作。我编辑了问题以阐明数据结构、我尝试过的内容以及得到的结果。下一步我应该尝试什么?
  • 您可能不需要排除 AttendeeForm 中的 event 字段,因为 inlineformset_factory 会处理它。
  • 其实,fieldsexclude 无论如何都不能在一个表单中同时使用——你应该将event 添加到fields 元组中。
  • 谢谢。我删除了排除项并将event 添加到元组中。仍然得到:(Hidden field event) The inline foreign key did not match the parent instance primary key. 你能想到什么会导致错误消息吗?
【解决方案2】:

如果将commit=False 传递给.save(),则可以修改对象并添加外键。

示例代码见Saving objects in the formset

【讨论】:

  • 我试过这个:formset.save(commit=False) 这给了我针对该行的以下错误:The Attendee could not be created because the data didn't validate. Ideas?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-07
  • 2019-02-05
  • 2018-06-08
  • 2018-03-30
  • 2021-12-11
  • 1970-01-01
  • 2020-09-16
相关资源
最近更新 更多