我从POST获取数据并通过此标准代码段验证它:
entry_formset = EntryFormSet(request.POST, request.FILES, prefix='entries')
if entry_formset.is_valid():
....
EntryFormSet模型覆盖外键字段小部件以显示文本字段。这样,用户可以输入现有密钥(通过Ajax实时搜索建议),或输入一个新密钥,该密钥将被无缝添加。
我使用这个try-except块来测试对象是否已经存在,如果没有,我会添加它。
entity_name = request.POST['entries-0-entity']
try:
entity = Entity.objects.get(name=entity_name)
except Entity.DoesNotExist:
entity = Entity(name=entity_name)
entity.slug = slugify(entity.name)
entity.save()
但是,我现在需要将entity
恢复到entry_formset
。它认为entries-0-entity
是一个字符串(它是如何进入的);如何直接访问entry_formset
的值并让它取代对象引用?
答案 0 :(得分:2)
我建议为表单集编写一个帮助工厂函数,以便您可以根据数据自定义显示窗口小部件。如下所示:
def make_entry_formset(initial_obj=None, custom_widget=forms.Textarea):
# these will be passed as keyword arguments to the ModelChoiceField
field_kwargs={'widget': custom_widget,
'queryset': Entity.objects.all()}
if initial_obj is not None:
field_kwargs.update({'initial': initial_obj})
class _EntryForm(forms.ModelForm):
entity = forms.ModelChoiceField(**field_kwargs)
class Meta:
model = Entry
return modelformset_factory(Entry, form=_EntryForm)
然后在您的视图代码中,您可以指定所需的窗口小部件以及是否绑定到初始Entity
对象。对于formset的初始呈现,您只需要一个Textarea
小部件而没有初始选择,您可以使用:
formset_class = make_entry_formset(custom_widget=forms.Textarea)
entry_formset = formset_class()
然后,如果要再次使用已定义is_valid()
对象的Entity
块之后)再次渲染它,可以使用:
formset_class = make_entry_formset(initial_obj=entity,
custom_widget=forms.HiddenInput)
entry_formset = formset_class(request.POST, request.FILES)
当然,您可以使用任何您喜欢的小部件,但使用HiddenInput
会阻止最终用户与此字段进行交互(您似乎希望将其绑定到您查看的entity
变量向上)。