Django-form_valid()与save()

时间:2018-07-04 11:39:56

标签: python django django-models django-forms django-views

在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字段,正如我在覆盖save()时覆盖的m2m值,但在覆盖form_valid时未保存他们开始保存。

2 个答案:

答案 0 :(得分:2)

关于您遇到的许多问题,我想是它们执行任务的顺序...表单>管理>模型,当您使用form_valid时,他们首先要做的是检查链中的其他事物,而使用保存是最后一次,也许可能是因为或其他原因...

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

form_valid 首先检查“清理”功能是否存在任何本机验证错误或自定义验证,然后才保存模型

保存只是保存而不进行验证,然后将其与表单一起进行验证

示例

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/

答案 1 :(得分:2)

如果使用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/')