#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 davidfischer-ch): Hi akaariai, Your mix-in is interesting but it has some issues, hopefully easy to fix. 1. This is actually broken by the `pre_save` logic for a simple reason : The `pre_save` methods are called inside the save, a.k.a inside the `super().save(...)` so your mix-in and my mix-in [https://github.com /davidfischer- ch/pytoolbox/blob/master/pytoolbox/django/models/mixins.py#L115 AutoUpdateFieldsMixin] will not detect those. Its a reason why I implemented [https://github.com/davidfischer- ch/pytoolbox/blob/master/pytoolbox/django/models/mixins.py#L153 CallFieldsPreSaveMixin]. I also implemented another mix-in (sometimes I feel like a DJ, doing many mixes),[https://github.com/davidfischer- ch/pytoolbox/blob/master/pytoolbox/django/models/mixins.py#L89 AutoRemovePKFromUpdateFieldsMixin] that will check if the primary key is set to a new value, then the intention of the developer is probably to duplicate the model by saving it with a new primary key. So the mix-in let Django save with its own default options for save. 2. `__dict__.copy()` is not sufficient, if one of the fields, is, for example, a `JSONField` then the content is a mutable type (`dict`). This container may contains nested mutable types, and you have to `deepcopy` to ensure your copy will reflect the unchanged data from the database and will not be modified. 3. your overload of `save()` isn't generic enough to support all possible arguments. Interesting you saved the data in `_state`. That's cleaner than my mix-in. I am thinking loudly, but is it more performant that any field set by the code should be updated regardless the value, something that will not happen often, or is it better to check for diff. Checking for diff will also double the memory usage for the data (is it any copy-on-write mix-in out here?). We also need to think about concurrent updates when designing a save-the- changes mix-in. For that reason I implemented another mix-in [https://github.com/davidfischer- ch/pytoolbox/blob/master/pytoolbox/django/models/mixins.py#L243 UpdatePreconditionsMixin]. I don't know what is the best option, but maybe its more explicit and intuitive that if the program sets the fields, that they will be saved regardless the value. Yes, many questions and thoughts. I am eager to heard about you guys. -- Ticket URL: <https://code.djangoproject.com/ticket/25363#comment:8> 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 django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/073.914a7fc2580f1fa3e489797dcd367a0c%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.