Don't use post_init signal for initialize tracker

This commit is contained in:
meanmail 2023-02-05 13:28:20 +04:00
parent 46d33923ba
commit 5663374890
3 changed files with 15 additions and 4 deletions

View file

@ -104,3 +104,4 @@
| Éric Araujo <merwok@netwok.org> | Éric Araujo <merwok@netwok.org>
| Őry Máté <ory.mate@cloud.bme.hu> | Őry Máté <ory.mate@cloud.bme.hu>
| Nafees Anwar <h.nafees.anwar@gmail.com> | Nafees Anwar <h.nafees.anwar@gmail.com>
| meanmail <github@meanmail.dev>

View file

@ -328,9 +328,9 @@ FieldTracker implementation details
This is how ``FieldTracker`` tracks field changes on ``instance.save`` call. This is how ``FieldTracker`` tracks field changes on ``instance.save`` call.
1. In ``class_prepared`` handler ``FieldTracker`` patches ``save_base`` and 1. In ``class_prepared`` handler ``FieldTracker`` patches ``save_base``,
``refresh_from_db`` methods to reset initial state for tracked fields. ``refresh_from_db`` and ``__init__`` methods to reset initial state for tracked fields.
2. In ``post_init`` handler ``FieldTracker`` saves initial values for tracked 2. In the patched ``__init__`` method ``FieldTracker`` saves initial values for tracked
fields. fields.
3. ``MyModel.save`` changes ``update_fields`` in order to store auto updated 3. ``MyModel.save`` changes ``update_fields`` in order to store auto updated
``modified`` timestamp. Complete list of saved fields is now known. ``modified`` timestamp. Complete list of saved fields is now known.

View file

@ -343,7 +343,7 @@ class FieldTracker:
wrapped_descriptor = wrapper_cls(field_name, descriptor, self.attname) wrapped_descriptor = wrapper_cls(field_name, descriptor, self.attname)
setattr(sender, field_name, wrapped_descriptor) setattr(sender, field_name, wrapped_descriptor)
self.field_map = self.get_field_map(sender) self.field_map = self.get_field_map(sender)
models.signals.post_init.connect(self.initialize_tracker) self.patch_init(sender)
self.model_class = sender self.model_class = sender
setattr(sender, self.name, self) setattr(sender, self.name, self)
self.patch_save(sender) self.patch_save(sender)
@ -356,6 +356,16 @@ class FieldTracker:
tracker.set_saved_fields() tracker.set_saved_fields()
instance._instance_initialized = True instance._instance_initialized = True
def patch_init(self, model):
original = getattr(model, '__init__')
@wraps(original)
def inner(instance, *args, **kwargs):
original(instance, *args, **kwargs)
self.initialize_tracker(model, instance)
setattr(model, '__init__', inner)
def patch_save(self, model): def patch_save(self, model):
self._patch(model, 'save_base', 'update_fields') self._patch(model, 'save_base', 'update_fields')
self._patch(model, 'refresh_from_db', 'fields') self._patch(model, 'refresh_from_db', 'fields')