如何从表单构造函数动态更新Django Form Meta类字段?

时间:2010-06-14 16:17:08

标签: django django-forms

我想动态更新Meta.fields。是否可以从Form构造函数中执行此操作?我尝试了以下操作,但在表单生成期间year没有出现。仅显示nametitle

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',)

5 个答案:

答案 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')