eugene
eugene

Reputation: 41665

django form save can't be used update a model instance?

I'm using django 1.8.4

djanog.forms.models.BaseModelForm.save reads as following

def save(self, commit=True):
    """
    Saves this ``form``'s cleaned_data into model instance
    ``self.instance``.

    If commit=True, then the changes to ``instance`` will be saved to the
    database. Returns ``instance``.
    """
    if self.instance.pk is None:
        fail_message = 'created'
    else:
        fail_message = 'changed'
    return save_instance(self, self.instance, self._meta.fields,
                         fail_message, commit, self._meta.exclude,
                         construct=False)

and save_instance has this..

def save_instance(form, instance, fields=None, fail_message='saved',
                  commit=True, exclude=None, construct=True):
    """
    Saves bound Form ``form``'s cleaned_data into model instance ``instance``.

    If commit=True, then the changes to ``instance`` will be saved to the
    database. Returns ``instance``.

    If construct=False, assume ``instance`` has already been constructed and
    just needs to be saved.
    """
    if construct:
        instance = construct_instance(form, instance, fields, exclude)

Basically, the above code (save_instance) updates the instance only when construct = True, but django code passes construct = False all the time.

Is this a bug in 1.8.4? :(

I just checked the code remains same until 1.8.9

Upvotes: 1

Views: 468

Answers (1)

Derek Kwok
Derek Kwok

Reputation: 13058

The construct_instance method is called in BaseModelForm._post_clean:

# BaseModelForm._post_clean()
# Update the model instance with self.cleaned_data.
self.instance = construct_instance(self, self.instance, opts.fields, construct_instance_exclude)

When this function is called, your "instance" will be updated with form data.

Note that _post_clean is called as part of BaseForm.full_clean, and is usually called indirectly by is_valid. This means that if you don't validate your form, calling save method will either fail with a new instance, or fail to update an old instance.

Upvotes: 2

Related Questions