Подтвердить что ты не робот

Django: удалить поле из подкласса Form

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, поэтому класс Meta с exclude не работает.

4b9b3361

Ответ 1

Вы можете изменить поля в подклассе, переопределив метод init:

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

Ответ 2

Django 1.7 обратился к этому в commit b16dd1fe019 для билета # 8620. В Django 1.7 становится возможным сделать nickname = None в подклассе, как предлагает OP. Из изменений документации в фиксации:

Можно отказаться от Field, унаследованного от родительского класса, затеняя его. Хотя для этой цели используется любое значение Field, рекомендуется использовать None, чтобы сделать его явным, что поле сбрасывается.

Ответ 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 во время сохранения)

Итак, для моей цели я использую второй метод.

Ответ 4

Мне не понравился факт (или так я понял), что исключение поля во втором классе с использованием "класса Meta:" по-прежнему приводит к тому, что неиспользуемое поле находится в db.

Возможно, самым простым способом является определение абстрактного класса с полями, разделяемыми обоими классами. Тогда два оригинальных класса выше становятся подклассами этого нового класса. Таким образом, пример, приведенный в начале этого потока, может выглядеть следующим образом. Это немного больше кода, но таким образом вы расширяете подкласс, а не исключаете (неполное) исключение из суперкласса.

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