barciewicz
barciewicz

Reputation: 3773

Django: can I omit ".save(commit=False)" in this case?

Here's the snippet from a view function for ModelForm in Django:

if form.is_valid():
    new_entry = form.save(commit=False)
    new_entry.topic = topic
    new_entry.save()

Would substituting this code with the following one have the same effect?:

if form.is_valid():
    form.topic = topic
    form.save()

If so, what is the use of creating new_entry object like in the first example?

Upvotes: 1

Views: 675

Answers (2)

Todor
Todor

Reputation: 16010

Would substituting this code with the following one have the same effect?:

No, form.save returns an instance of the Model, setting form.topic do not change this model. What you can do is this:

if form.is_valid():
    form.instance.topic = topic
    new_entry = form.save()

but make sure you don't have topic as a field in your form, otherwise the .save will probably override what you just set.

Another approach would be to just pass an instance with a topic to the form.

instance = MyModel(topic=topic)
form = MyForm(request.POST, instance=instance)
if form.is_valid():
    new_entry = form.save()

Upvotes: 3

bruno desthuilliers
bruno desthuilliers

Reputation: 77892

Would substituting this code with the following one have the same effect?

Obviously not - your form object is not the model instance returned by form.save(). Your current (first snippet) solution is the official canonical solution, the other option would be to pass the topic to the form and override your form's save() method to take care of it:

# yourforms.py
class MyForm(forms.ModelForm):

    # your existing code here

    def __init__(self, *args, **kw):
        # if "topic" is required for your model, 
        # you may want to either have a default value
        # for "topic" or raise if it's not passed.
        self.topic = kw.pop("topic", None)
        super(MyForm, self).__init__(*args, **kw)

   def save(self, commit=False):
       instance = super(MyForm, self).save(commit=commit)
       instance.topic = self.topic
       if commit:
           instance.save()
       return instance

And in your view:

# your existing code here    
form = MyForm(request.POST, ..., topic=topic)
if form.is_valid():
    new_entry = form.save()

As you can see it doesn't make the code any simpler overall - you actually have (a bit) more to add to the form than you save in the view - but at least it makes the view code cleaner (IMHO).

Note that in this case the new_entry variable is only useful if you need it later in the view, else you can dispense with it.

Upvotes: 1

Related Questions