代码之家  ›  专栏  ›  技术社区  ›  Thierry Lam

如何从表单构造函数动态更新django表单元类字段?

  •  17
  • Thierry Lam  · 技术社区  · 14 年前

    我想更新 Meta.fields 动态地。是否可以从表单构造函数中执行此操作?我试过以下方法,但是 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',)
    
    5 回复  |  直到 14 年前
        1
  •  17
  •   Daniel Roseman    14 年前

    不,那不行。元被元类(令人惊讶的是)解析,甚至在您到达之前 __init__ .

    这样做的方法是手动将字段添加到 self.fields :

    def __init__(self, *args, **kwargs):
        super(PartialAuthorForm, self).__init__(*args, **kwargs)
        self.fields['year'] = forms.CharField(whatever)
    
        2
  •  14
  •   mkoistinen    10 年前

    其他人的回答是很好的(尤其是@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']
    

    如上文所述,用另一种方法来做是相当复杂的,但有条件地放弃它是非常直接的。=)

        3
  •  4
  •   Bran Handley    12 年前

    说要用的答案 __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 也。

        4
  •  0
  •   Bernhard Vallant    14 年前

    内部 Meta 当通过创建实例之前的元类创建ModelForm类时,类已被处理。做你想做的事 __init__ 不会那样工作的!
    您可以访问dictionary中创建的字段对象 self.fields 你可以做一些像 self.fields['year'] = forms.MyFormField(...) .

        5
  •  0
  •   Simanas    9 年前

    通过重写窗体的uu init_uuu方法将字段添加到模型窗体将不起作用,因为模型窗体字段在窗体构造函数调用之前已初始化。因此,您将不会从实际模型中获取任何值到表单,并且在调用save之后,您的值将不会保存到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')