【问题标题】:How to remove a field from the parent Form in a subclass?如何从子类中的父表单中删除字段?
【发布时间】:2013-03-11 12:53:39
【问题描述】:
class LoginForm(forms.Form):
    nickname = forms.CharField(max_length=100)
    username = forms.CharField(max_length=100)
    password = forms.CharField(widget=forms.PasswordInput)


class LoginFormWithoutNickname(LoginForm):
    # i don't want the field nickname here
    nickname = None #??

有没有办法做到这一点?

注意:我没有ModelForm,因此带有excludeMeta 类不起作用。

【问题讨论】:

    标签: python django forms inheritance field


    【解决方案1】:

    您可以通过重写 init 方法来更改子类中的字段:

    class LoginFormWithoutNickname(LoginForm):
        def __init__(self, *args, **kwargs):
            super(LoginFormWithoutNickname, self).__init__(*args, **kwargs)
            self.fields.pop('nickname')
    

    【讨论】:

    • 谢谢,请将__init__(self)编辑成__init__(self, *args, **kwargs)
    • 不适用于内联的管理表单,模板尝试渲染它们,我得到一个 KeyError。
    【解决方案2】:

    Django 1.7 在提交 b16dd1fe019 中为票证 #8620 解决了这个问题。在 Django 1.7 中,可以按照 OP 的建议在子类中执行 nickname = None 。从提交中的文档更改:

    可以通过隐藏从父类继承的Field 来选择退出它。虽然任何非Field 值都适用于此目的,但建议使用None 来明确表明某个字段正在被无效。

    【讨论】:

    • 有效吗?由于“无效”意味着将取值无?因为我尝试并使用“meta -> exclude =[]”按我的预期工作,所以“你的”方式使用该字段的默认值,等于 None
    • 请注意,这仅在父类声明该字段时才有效。一般来说,这不适用于ModelForms。
    • 是否尝试过此解决方案以删除 TicketForm 中的“assigned_to”。该字段确实按预期从表单中消失了,但它现在在创建工单时抛出错误。给出了默认值,但它不在cleaned_data 中。他们是否可以在表单中隐藏此特定字段,同时仍将通过 clean_data 发送?
    【解决方案3】:

    我找到了,如果有兴趣请评论。

    (在 Django 1.7.4 中) 扩展表单,代码如下:

    class MyForm(forms.ModelForm):
    
        def __init__(self, *args, **kwargs):
            super(MyForm, self).__init__(*args, **kwargs)
    
            for key, field in self.fields.iteritems():
                self.fields[key].required = False
    
        class Meta:
            model = MyModel
            exclude = []
    
        field_1 = forms.CharField(label="field_1_label")
        field_2 = forms.CharField(label="field_2_label", widget=forms.Textarea(attrs={'class': 'width100 h4em'}),)
        field_3 = forms.CharField(label="field_3_label", widget=forms.TextInput(attrs={'class': 'width100'}),)
        field_4 = forms.ModelChoiceField(label='field_4_label', queryset=AnotherModel.objects.all().order_by("order") )
    
    class MyForm_Extended_1(MyForm):
        field_1 = None
    
    
    class MyForm_Extended_2(MyForm):
        class Meta:
            model = MyModel
            exclude =[
                        'field_1',
                    ]
    

    MyForm_Extended_1 设置 field_1 为 None,(db 中的列更新为 Null)

    MyForm_Extended_2 忽略字段(保存时忽略db中的列)

    因此,出于我的目的,我使用第二种方法。

    【讨论】:

    • 非常有用且唯一的方法是从 forms.Form 中删除字段(无模型)
    【解决方案4】:

    我不喜欢这样一个事实(或者我理解),使用“class Meta:”排除第二类中的字段仍然会导致未使用的字段在数据库中。

    也许最简单的方法是定义一个具有两个类共享字段的抽象类。然后上面的两个原始类成为这个新类的子类。因此,在该线程开头给出的示例可能如下所示。代码有点多,但这样您扩展子类而不是从超类中(不完全)排除。

    class LoginForm_Common(forms.Form):
        username = forms.CharField(max_length=100)
        password = forms.CharField(widget=forms.PasswordInput)
        class Meta:
            abstract = True
    
    class LoginForm(LoginForm_Common):
        nickname = forms.CharField(max_length=100)
    
    class LoginFormWithoutNickname(LoginForm_Common):
        pass
    

    【讨论】:

      猜你喜欢
      • 2016-01-30
      • 1970-01-01
      • 2017-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-15
      • 2019-03-04
      • 2019-07-28
      相关资源
      最近更新 更多