Django - form_valid() vs save()

眉间皱痕 提交于 2020-12-30 07:40:10

问题


In django forms, for saving other data I usually use form_valid() but as I can also use save() method of formclass.

Today I overrided save() instead of form_valid() and I got problem with my manytomanyfield.

When using , the values of manytomanyfield are not saved but when I use form_valid() they start saving. Can anybody tell me the reason and what are the differences between both, which is the most convenient method and in what situation?

Here is my overriding of save() method:

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

When I override form_valid() method:

   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)

sizes,colours and regions are m2m fields, as I mentioned when I overrides save() values of m2m not get saved but when I overrides form_valid they start saving.


回答1:


If you save a form with commit=False, you must call the form's save_m2m method to save the many-to-many data. See the docs for more info.

If you decide to use the form_valid method, I would change the following things:

  • update the instance returned by form.save() and save it, instead of calling form.save() again.
  • explicitly call form.save_m2m()
  • return a redirect response instead of calling super().form_valid() (which will save the form again)

Putting that together, you get:

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:


About your problem with manytomany i guess is the order they do things... Form > Admin > Models, when you use form_valid is the first thing they do before check other things in chain, while using save is the last, maybe can be because or other things too...

The best way is always use form_valid instead of raw save

form_valid first check the Clean function if there is any native validations errors or custom validations and only then save your models

save just save it without validate then with your form with your validations

Example

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."
                )

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



来源:https://stackoverflow.com/questions/51172820/django-form-valid-vs-save

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!