从this question我想把我的表单从常规的Form
转换为ModelForm
,这样我就可以利用ModelForm
中的instance
参数。
这是我当前的表单代码:
class OrderDetailForm(forms.Form):
def __init__(
self,
user,
can_edit_work_type=None,
can_edit_vendor=None,
can_edit_note=None,
*args,
**kwargs
):
super(OrderDetailForm, self).__init__(*args, **kwargs)
if can_edit_work_type:
self.fields['work_type'] = forms.ChoiceField(choices=Order.WORK_TYPE_CHOICES)
if can_edit_vendor:
self.fields['vendor'] = forms.ModelChoiceField(
queryset=Vendor.objects.all(),
empty_label="Choose a vendor",
)
if can_edit_note:
self.fields['note'] = forms.CharField(widget=forms.Textarea)
def clean(self):
super(OrderDetailForm, self).clean()
if 'note' in self.cleaned_data:
if len(self.cleaned_data['note']) < 50:
self._errors['note'] = self.error_class([u"Please enter a longer note."])
del self.cleaned_data['note']
return self.cleaned_data
如您所见,我有一些if
语句来确定字段是否在表单中显示(逻辑上它意味着某些用户只能编辑字段的某些部分)。
在ModelForm
中我该怎么做?我知道fields
是一个元组,所以不能像我在Form
中那样附加它。所以我想做些
class OrderDetailForm(forms.ModelForm):
class Meta:
model = Order
# fields = ('work_type', 'vendor', 'note') I can't do that since I need to be able to control it. See below.
# Can I control widgets even if that field doesn't exist?
widgets = {
'note': forms.Textarea(),
}
def __init__(
self,
user,
can_edit_work_type=None,
can_edit_vendor=None,
can_edit_note=None,
*args,
**kwargs
):
super(OrderDetailForm, self).__init__(*args, **kwargs)
fields = []
if can_edit_work_type:
fields.append('work_type')
if can_edit_vendor:
fields.append('vendor')
if can_edit_note:
fields.append('note')
self.Meta.fields = tuple(fields) # Does this work?
def clean(self):
super(OrderDetailForm, self).clean()
if 'note' in self.cleaned_data:
if len(self.cleaned_data['note']) < 50:
self._errors['note'] = self.error_class([u"Please enter a longer note."])
del self.cleaned_data['note']
return self.cleaned_data
有可能吗?如何控制ModelForm
中的字段?
另一种可能的方法是在视图中生成内联表单类以根据请求排除字段,例如,为订单模型定义一个普通的模型表单,称为OrderDetailForm:
在视图中,例如“编辑订单”,根据OrderDetailForm创建自定义表单:
ModelForm
api与常规的Form
api非常相似。它的优点是,除了像默认小部件、实例kwarg和save方法这样的方便之外,现在还可以获得model validation。fields
attr
仍然是dict
样的。您可以看到由元类here生成的字段。然后,通过through到inheritance并调用BaseModelForm.__init__
中的super()
,我们得到declared fields,originallyaSortedDict
的deepcopy
。这对Form
和ModelForm
都是常见的,这两个子类都是BaseForm
。把字段放在exclude中,然后像在原始
__init__
中那样添加它们。用同样的方法清洗。
然后,您可以重写
save
方法:您可以调用super()
以取回对象,并根据需要处理cleaned_data
中的数据。相关问题 更多 >
编程相关推荐