【问题标题】:How do you update a Django Form Meta class fields dynamically from the form constructor?如何从表单构造函数动态更新 Django Form Meta 类字段?
【发布时间】:2011-03-03 14:29:54
【问题描述】:

我想动态更新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',)

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    通过覆盖表单的 __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')
    

    【讨论】:

      【解决方案2】:

      其他人的答案很棒(尤其是@BranHandley 的),但有时,有条件地删除 是最简单的方法。显然这不适用于动态创建的东西,但是如果您只需要可选地包含一个字段,那么请尝试这样。

      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']
      

      如上所述,以另一种方式进行操作可能会相当复杂,但有条件地放弃它是非常简单的。 =)

      【讨论】:

      • 我认为这是最优雅的解决方案,因为您不会失去 ModelForms 类的魔力。但是不要忘记在 init 中调用 super()。
      【解决方案3】:

      说使用__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

      【讨论】:

      • 很好的答案,但return 没有被识别并且() 在函数名称后丢失。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        不,这行不通。在您到达 __init__ 之前,元类已被解析 - 令人惊讶的是 - 元类。

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

        def __init__(self, *args, **kwargs):
            super(PartialAuthorForm, self).__init__(*args, **kwargs)
            self.fields['year'] = forms.CharField(whatever)
        

        【讨论】:

          猜你喜欢
          • 2011-01-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-09
          • 1970-01-01
          • 2017-06-06
          • 1970-01-01
          相关资源
          最近更新 更多