web-dev-qa-db-ja.com

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クラスは機能しません。

39
apelliciari

initメソッドをオーバーライドして、サブクラスのフィールドを変更できます。

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

Django 1.7はこれをコミットで解決しました b16dd1fe019 for ticket #862 。 Django 1.7では、nickname = None OPが示すように、サブクラス内。コミットのドキュメントの変更から:

シャドーイングすることにより、親クラスから継承されたFieldからオプトアウトすることができます。この目的にはField以外の値も機能しますが、Noneを使用して、フィールドがnullになっていることを明示することをお勧めします。

10
cjerdonek

気づいたらコメントしてください。

(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はフィールドを無視します(保存中はデータベースの列を無視します)

したがって、私の目的では、2番目の方法を使用します。

5
Gromish

「クラスメタ:」を使用して2番目のクラスのフィールドを除外しても、未使用のフィールドがデータベースに残っているという事実は気に入らなかった(または私は理解した)。

おそらく最も簡単な方法は、両方のクラスで共有されるフィールドを持つ抽象クラスを定義することです。次に、上記の2つの元のクラスがこの新しいクラスのサブクラスになります。したがって、このスレッドの最初に示した例は次のようになります。少しコードが増えますが、この方法では、スーパークラスからの(不完全な)除外を行うのではなく、サブクラスを拡張します。

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
3
Guddo