web-dev-qa-db-ja.com

Django-form_valid()とsave()

Django=フォームでは、他のデータを保存するために、通常form_valid()を使用しますが、formclassのsave()メソッドも使用できます。

今日、save()の代わりにform_valid()をオーバーライドしました。manytomanyfieldで問題が発生しました。

を使用すると、manytomanyfieldの値は保存されませんが、form_valid()を使用すると保存が開始されます。誰かが理由を教えてください、そして両方の違いは何ですか?これは最も便利な方法であり、どのような状況ですか?

これがsave()メソッドのオーバーライドです。

class ProductCreateForm(forms.ModelForm):
    sizes = make_ajax_field(ProductCreateModel,'sizes','sizes')
    colours = make_ajax_field(ProductCreateModel,'colours','colours')

    class Meta:
        model = ProductCreateModel

        fields = ('title','category',
                    'regions',)

    def __init__(self,*args,**kwargs):
        self.request = kwargs.pop("request")
        super(ProductCreateForm, self).__init__(*args, **kwargs)

    def save(self):
        product = super(ProductCreateForm, self).save(commit=False)
        user =  self.request.user

        product.location = user.user_location
        product.save()
        return product

Form_valid()メソッドをオーバーライドすると:

   def get_form_kwargs(self):
       kwargs = super(ProductCreateView,self).get_form_kwargs()
       kwargs.update({'request':self.request})
       return kwargs

   def form_valid(self, form):
       product = form.save(commit=False)
       user =  self.request.user
       form.instance.user = user
       form.instance.location = user.user_location
       form.save()
       return super(ProductCreateView, self).form_valid(form)

sizescoloursregionsはm2mフィールドです。m[2]のsave()値をオーバーライドすると、保存されませんが、form_validをオーバーライドすると、節約。

5
Pankaj Sharma

Manytomanyの問題について私が推測するのは、それらが実行する順序です...フォーム>管理>モデル、form_validを使用すると、チェーン内の他のことを確認する前に最初に実行しますが、保存を使用すると、最後になります。または他のもの...

最良の方法は、常にraw saveではなくform_validを使用することです

form_valid最初に、ネイティブ検証エラーまたはカスタム検証があるかどうかClean関数を確認し、次にモデルのみを保存します

save検証なしで保存し、検証付きのフォームで保存します

from Django import forms

class ContactForm(forms.Form):
    # Everything as before.
    ...

    def clean(self):
        cleaned_data = super().clean()
        cc_myself = cleaned_data.get("cc_myself")
        subject = cleaned_data.get("subject")

        if cc_myself and subject:
            # Only do something if both fields are valid so far.
            if "help" not in subject:
                raise forms.ValidationError(
                    "Did not send for 'help' in the subject despite "
                    "CC'ing yourself."
                )

ソース: https://docs.djangoproject.com/en/2.0/ref/forms/validation/

2
Diego Vinícius

_commit=False_を使用してフォームを保存する場合は、フォームの_save_m2m_メソッドを呼び出して、多対多のデー​​タを保存する必要があります。詳細は the docs を参照してください。

_form_valid_メソッドを使用する場合は、次の点を変更します。

  • form.save()を再度呼び出す代わりに、form.save()によって返されたインスタンスを更新して保存します。
  • 明示的にform.save_m2m()を呼び出します
  • super().form_valid()を呼び出す代わりにリダイレクト応答を返します(フォームを再度保存します)

まとめると、次のようになります。

_def form_valid(self, form):
    product = form.save(commit=False)
    product.user =  self.request.user
    product.location.location = user.user_location
    product.save()
    form.save_m2m()
    return redirect('/success-url/')
_
2
Alasdair