Django - form_valid() 与 save()

Pan*_*rma 8 python django django-models django-forms django-views

在 Django 表单中,为了保存我通常使用的其他数据,form_valid()但我也可以使用save()formclass 的方法。

今天我覆盖了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
Run Code Online (Sandbox Code Playgroud)

当我覆盖 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)
Run Code Online (Sandbox Code Playgroud)

sizescolours并且regions是 m2m 字段,正如我提到的,当我覆盖save()m2m 的值时不会被保存,但是当我覆盖form_valid它们时,它们开始保存。

Ala*_*air 7

如果使用 保存表单commit=False,则必须调用表单的save_m2m方法来保存多对多数据。有关更多信息,请参阅文档

如果您决定使用该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/')
Run Code Online (Sandbox Code Playgroud)


Die*_*ius 1

关于你的问题,我猜是他们做事的顺序...表单>管理>模型,当你使用form_valid时,他们在检查链中的其他事情之前做的第一件事是,而使用save是最后一个,也许是因为或者其他的东西也...

最好的方法是始终使用 form_valid 而不是原始保存

form_valid首先检查 Clean 函数是否存在任何本机验证错误或自定义验证,然后才保存模型

保存只需保存它而不进行验证,然后使用带有验证的表单

例子

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."
                )
Run Code Online (Sandbox Code Playgroud)

来源: https: //docs.djangoproject.com/en/2.0/ref/forms/validation/