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.
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:
form.save()
and save it, instead of calling form.save()
again.form.save_m2m()
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/')
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With