Question

I am processing a ModelForm, and both of these seem to return identical results:

if request.method == 'POST':
    form = FooForm(request.POST)
    if form.is_valid():
        bar = form.save(commit = False)
        bar.user = request.user
        form.save()


if request.method == 'POST':
    form = FooForm(request.POST)
    if form.is_valid():
        bar = form.save(commit = False)
        bar.user = request.user         
        bar.save()               # calling save on bar instead of on the form

In terms of how these save data and relations between data, is there any difference in these two? The second approach doesn't seem to work when I need to use bar.save_m2m(), which makes me think that the first approach is the right way to go. However, the logic of the second approach makes more sense to me. Can anyone clarify for me which one of these is more correct and why? I am worried that I am unintentionally processing data incorrectly and setting my app up for problems down the line.

Was it helpful?

Solution

From Django's website, probably this will clear up what you should do:

# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()

# Now, save the many-to-many data for the form.
>>> f.save_m2m()

From https://docs.djangoproject.com/en/1.6/topics/forms/modelforms/

This is extracted from the source code of Django 1.6.2:

if commit:
    # If we are committing, save the instance and the m2m data immediately.
    instance.save()
    save_m2m()
else:
    # We're not committing. Add a method to the form to allow deferred
    # saving of m2m data.
    form.save_m2m = save_m2m
return instance

This is the reason why if after Ex1:form.save() you call bar.save_m2m() everything will be fine, you will be executing a normal save() step by step. The Base class is returning its instance each time so if you call save() it will save the same instance you are pointing to from outside and that you just modified (Warning: are you using it as a global variable?)...and anyway you can not be sure for how long this method will work as you expect since nowhere in the documentation says the instance returned when calling form.save(commit=False) is the same instance used when you call form.save() few lines below.

As far as I know you wanted to know which way is better to avoid future problems...my recommendation is: go with the second one!.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top