#25363: Model fields pre_save not called if force_insert=True
-------------------------------------+-------------------------------------
     Reporter:  davidfischer-ch      |                    Owner:
                                     |  davidfischer-ch
         Type:  Bug                  |                   Status:  closed
    Component:  Database layer       |                  Version:  1.8
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:  needsinfo
     Keywords:  pre_save,save        |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by akaariai):

 A clean mix-in to track updated fields to both make UPDATE queries
 lighter, and to also skip update completely when no data has changed is a
 big issue for me. So, if we can make that easier for users, I think we
 should do that.

 BTW here is my approach for this issue:
 {{{
 class ModTrackingMixin(object):
     @classmethod
     def from_db(cls, *args, **kwargs):
         new = super().from_db(*args, **kwargs)
         new._state.db_vals = new.__dict__.copy()
         return new

     def save(self, update_fields=None):
         if hasattr(self._state, 'db_vals') and update_fields is None:
             changed = []
             orig = self._state.db_vals
             for f, fname in [(f, f.attname) for f in
 self._meta.get_fields()
                                        if f.concrete]:
                 if (fname in orig and
                          f.to_python(getattr(self, fname)) !=
 orig.get(fname, NO_VALUE)):
                     changed.append(fname)
             return super().save(update_fields=changed)
         else:
             return super().save(update_fields=update_fields)


 class Organization(models.Model):
     code = models.CharField(max_length=20)
     name= models.CharField(max_length=100)

     class Meta:
         db_table = 'organization'


 class ModTrackingOrganization(ModTrackingMixin, Organization):
     class Meta:
         proxy = True
 }}}

 The idea is that if you do:
 {{{
 o = ModTrackingOrganization.objects.first()
 o.name = o.name
 o.save()
 }}}
 Then the save will actually be silently skipped (as no data has changed in
 the DB).

 I wonder if this is actually broken for some cases by the pre_save logic
 we have currently in Django?

--
Ticket URL: <https://code.djangoproject.com/ticket/25363#comment:7>
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/073.3d9ebb099cc3d573813ff1b93bc7a25f%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to