Django:从表单子类中移除一个字段。

时间:2022-12-05 19:32:58
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 #??

Is there a way to achieve this?

有办法做到这一点吗?

Note: i don't have a ModelForm, so the Meta class with exclude doesn't work.

注意:我没有模型形式,所以排除的元类不起作用。

4 个解决方案

#1


56  

You can alter the fields in a subclass by overriding the init method:

可以通过覆盖init方法来更改子类中的字段:

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

#2


9  

Django 1.7 addressed this in commit b16dd1fe019 for ticket #8620. In Django 1.7, it becomes possible to do nickname = None in the subclass as the OP suggests. From the documentation changes in the commit:

Django 1.7在提交b16dd1fe019的过程中使用了#8620。在Django 1.7中,可以按照OP的建议在子类中执行昵称= None。从提交文件的变更:

It's possible to opt-out from a Field inherited from a parent class by shadowing it. While any non-Field value works for this purpose, it's recommended to use None to make it explicit that a field is being nullified.

可以通过隐藏从父类继承的字段选择退出。尽管任何非字段值都适用于此目的,但建议使用None来显式地表示字段正在被空化。

#3


3  

I found that, please comment if interested.

我发现,如果有兴趣请评论。

(in Django 1.7.4) extending forms, with following code:

(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 set field_1 as None, (the column in db is updated as Null)

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

MyForm_Extended_2 ignore the field (ignore the column in db during the save)

MyForm_Extended_2忽略字段(在保存期间忽略db中的列)

So, for my purpose, I use the second method.

对于我的目的,我使用第二种方法。

#4


1  

I didn't like the fact (or so I understood) that the exclusion of a field in the second class using "class Meta:" still results in the unused field being in the db.

我不喜欢这样的事实(或者我理解的那样):在第二类中使用“class Meta:”排除字段仍然会导致未使用的字段位于db中。

Perhaps the simplest way is to define an abstract class that has the fields shared by both classes. Then the two original classes above become subclasses of this new class. So the example given at the start of this thread might look the following. It's a bit more code, but this way you extend a subclass rather than do an (incomplete) exclusion from a super class.

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

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

#1


56  

You can alter the fields in a subclass by overriding the init method:

可以通过覆盖init方法来更改子类中的字段:

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

#2


9  

Django 1.7 addressed this in commit b16dd1fe019 for ticket #8620. In Django 1.7, it becomes possible to do nickname = None in the subclass as the OP suggests. From the documentation changes in the commit:

Django 1.7在提交b16dd1fe019的过程中使用了#8620。在Django 1.7中,可以按照OP的建议在子类中执行昵称= None。从提交文件的变更:

It's possible to opt-out from a Field inherited from a parent class by shadowing it. While any non-Field value works for this purpose, it's recommended to use None to make it explicit that a field is being nullified.

可以通过隐藏从父类继承的字段选择退出。尽管任何非字段值都适用于此目的,但建议使用None来显式地表示字段正在被空化。

#3


3  

I found that, please comment if interested.

我发现,如果有兴趣请评论。

(in Django 1.7.4) extending forms, with following code:

(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 set field_1 as None, (the column in db is updated as Null)

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

MyForm_Extended_2 ignore the field (ignore the column in db during the save)

MyForm_Extended_2忽略字段(在保存期间忽略db中的列)

So, for my purpose, I use the second method.

对于我的目的,我使用第二种方法。

#4


1  

I didn't like the fact (or so I understood) that the exclusion of a field in the second class using "class Meta:" still results in the unused field being in the db.

我不喜欢这样的事实(或者我理解的那样):在第二类中使用“class Meta:”排除字段仍然会导致未使用的字段位于db中。

Perhaps the simplest way is to define an abstract class that has the fields shared by both classes. Then the two original classes above become subclasses of this new class. So the example given at the start of this thread might look the following. It's a bit more code, but this way you extend a subclass rather than do an (incomplete) exclusion from a super class.

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

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