#22346: ModelForm modifies the Model instance before save is called
-------------------------------+--------------------
     Reporter:  lehins@…       |      Owner:  nobody
         Type:  Uncategorized  |     Status:  new
    Component:  Forms          |    Version:  1.6
     Severity:  Normal         |   Keywords:
 Triage Stage:  Unreviewed     |  Has patch:  0
Easy pickings:  0              |      UI/UX:  0
-------------------------------+--------------------
 So here is a use case that is relevant to me:
 I need a model instance's primary key(pk) before I save the model, but
 only after the model form is validated. In particular I needed it to use
 in a pre_save method on a file field. So my logical solution was:

 {{{
 try:
    instance = CustomModel.objects.get(pk=pk)
 except CustomModel.DoesNotExist:
    instance = CustomModel()
 form = CustomModelForm(instance=instance, data=request.POST,
 files=request.FILES))
 if form.is_valid():
    if not instance.pk:
        instance.save() # saves the model while generating a pk
    instance = form.save()
 }}}

 To my disappointment, after a few wasted hours, I figured out that binding
 data to a model instance modifies that instance, so when I am calling
 instance.save() it already contains data from the form, before even
 calling form.save() method.
 After finding this ticket: #14885 I also noticed that it may be a partial
 update of the model instance. Despite closed ticket I couldn't find it in
 current documentation.
 In my opinion it is completely illogical. Model instance should only be
 modified only upon form.save() call, this would also give a real use case
 for the existence of commit=False argument: "apply cleaned form data to
 model instance, but do not commit to database."
 Even [https://docs.djangoproject.com/en/1.6/topics/forms/modelforms/#the-
 save-method documentation] follows the logic I am proposing: "A subclass
 of ModelForm can accept an existing model instance as the keyword argument
 instance; if this is supplied, save() will update that instance"

 Overall it sounds to me like a side effect or a bug. If it truly is an
 unavoidable side-effect, I believe, we should get at least a really good
 explanation of it in the documentation.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/22346>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/059.e904f5a89a297343894b8762a36876f6%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to