Это на самом деле довольно просто (настройки условного поля) - вот небольшой пример:
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.