我想动态更新Meta.fields
。是否可以从Form构造函数中执行此操作?我尝试了以下操作,但在表单生成期间year
没有出现。仅显示name
和title
。
class Author(models.Model):
name = ...
title = ...
year = ...
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title')
def __init__(self, *args, **kwargs):
self.Meta.fields += ('year',)
答案 0 :(得分:17)
不,那不行。在您进入__init__
之前,Meta被令人惊讶地解析为元类。
执行此操作的方法是手动将字段添加到self.fields
:
def __init__(self, *args, **kwargs):
super(PartialAuthorForm, self).__init__(*args, **kwargs)
self.fields['year'] = forms.CharField(whatever)
答案 1 :(得分:14)
其他人的答案很棒(特别是@BranHandley's),但有时候,最容易有条件地删除。显然,这不适用于动态创建的内容,但如果您只需要选择包含某个字段,那么请尝试这样做。
class MyModelForm(ModelForm):
class Meta:
model = MyModel
fields = ['normalField', 'conditionalField', ]
def __init__(self, *args, **kwargs):
super(MyModelForm, self).__init__(*args, **kwargs)
if condition is True:
del self.fields['conditionalField']
如上所述,以另一种方式进行操作可能相当复杂,但有条件地放弃它是非常简单的。 =)
答案 2 :(得分:4)
说使用__init__
的答案会起作用但你失去了与模型的连接(假设你要添加的字段在模型上)。相反,您可以动态创建一个继承自现有表单的新表单。
def my_form_factory:
class ModifiedAuthorForm(PartialAuthorForm):
class Meta(PartialAuthorForm.Meta):
fields = PartialAuthorForm.Meta.fields
if hasattr(fields, 'append'):
fields.append('year')
else:
fields = fields + ('year',)
return ModifiedAuthorForm
当然,如果你想要健壮,你应该检查你添加的字段是否已经在fields
中,你也应该处理exclude
。
答案 3 :(得分:0)
当通过元类创建ModelForm类时,已经处理了内部Meta
类,该元类是在创建实例之前创建的。在__init__
执行您尝试执行的操作将无法正常工作!
您可以在dictonary self.fields
中访问创建的字段对象,例如。你可以做self.fields['year'] = forms.MyFormField(...)
之类的事情。
答案 4 :(得分:0)
通过覆盖表单的__init__方法向模型表单添加字段将不起作用,因为模型表单字段在表单构造函数调用之前被初始化。因此,您不会从实际模型获取任何值到表单,并且在保存调用后您的值将不会保存到db。
你需要使用python的完整之美并使用像这样的类装饰器;)
def year_decorator(form_class):
class ModifiedForm(form_class):
class Meta(form_class.Meta):
if isinstance(form_class.Meta.model, Author):
fields = form_class.Meta.fields + ('year',)
return ModifiedForm
@year_decorator
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title')