这实际上相当简单(条件字段设置) - 这是一个简单的示例:
from django.forms import Modelform
from django.forms.widgets import HiddenInput
class SomeForm(ModelForm):
def __init__(self, *args, **kwargs):
# call constructor to set up the fields. If you don't do this
# first you can't modify fields.
super(SomeForm, self).__init__(*args, **kwargs)
try:
# make somefunc return something True
# if you can change the driver.
# might make sense in a model?
canchangedriver = self.instance.somefunc()
except AttributeError:
# unbound form, what do you want to do here?
canchangedriver = True # for example?
# if the driver can't be changed, use a input=hidden
# input field.
if not canchangedriver:
self.fields["Drivers"].widget = HiddenInput()
class Meta:
model = SomeModel
所以,这里的关键点:
-
self.instance 表示绑定的对象,如果表单已绑定。我相信它是作为命名参数传入的,因此在 kwargs 中,父构造函数使用它来创建 self.instance。
- 您可以在调用父构造函数后修改字段属性。
- 小部件是表单的显示方式。 HiddenInput 基本上是指
<input type="hidden" .../>。
有一个限制;如果我修改提交的 POST/GET 数据,我可以篡改输入以更改值。如果您不希望这种情况发生,需要考虑的是覆盖表单的验证 (clean()) 方法。请记住,Django 中的所有内容都只是对象,这意味着您实际上可以修改类对象并向它们随机添加数据(尽管它不会被持久化)。因此,在您的 __init__ 中,您可以:
self.instance.olddrivers = instance.drivers.all()
然后在您的干净方法中为所述表单:
def clean(self):
# validate parent. Do this first because this method
# will transform field values into model field values.
# i.e. instance will reflect the form changes.
super(SomeForm, self).clean()
# can we modify drivers?
canchangedriver = self.instance.somefunc()
# either we can change the driver, or if not, we require
# that the two lists are, when sorted, equal (to allow for
# potential non equal ordering of identical elements).
# Wrapped code here for niceness
if (canchangedriver or
(sorted(self.instance.drivers.all()) ==
sorted(self.instance.olddrivers))):
return True
else:
raise ValidationError() # customise this to your liking.