这实际上相当简单(条件字段设置) - 这是一个简单的示例:
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?
can_change_driver = self.instance.somefunc()
except AttributeError:
# unbound form, what do you want to do here?
can_change_driver = True # for example?
# if the driver can't be changed, use a input=hidden
# input field.
if not can_change_driver:
self.fields["Drivers"].widget = HiddenInput()
class Meta:
model = SomeModel
因此,要点如下:
-
self.instance
如果表单已绑定,则表示绑定对象。我相信它是作为命名参数传递的,因此在kwargs
,父构造函数用来创建self.instance
.
- 您可以在调用父构造函数后修改字段属性。
- 小部件是表单的显示方式。隐藏输入基本上意味着
<input type="hidden" .../>
.
有一个限制:如果我修改提交的 POST/GET 数据,我可以篡改输入以更改值。如果您不希望发生这种情况,则需要考虑重写表单的验证 (clean()) 方法。请记住,Django 中的所有内容都只是对象,这意味着您实际上可以修改类对象并向其中随机添加数据(但不会持久化)。所以在你的__init__
你可以:
self.instance.olddrivers = instance.drivers.all()
然后在所述形式的 clean 方法中:
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?
can_change_driver = 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 (can_change_driver or
(sorted(self.instance.drivers.all()) ==
sorted(self.instance.olddrivers))):
return True
else:
raise ValidationError() # customise this to your liking.