From 5663374890988209c72fccbe50f920a6ce37c7d1 Mon Sep 17 00:00:00 2001 From: meanmail Date: Sun, 5 Feb 2023 13:28:20 +0400 Subject: [PATCH 1/2] Don't use `post_init` signal for initialize tracker --- AUTHORS.rst | 1 + docs/utilities.rst | 6 +++--- model_utils/tracker.py | 12 +++++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 2c875fe5..557f7cbe 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -104,3 +104,4 @@ | Éric Araujo | Őry Máté | Nafees Anwar +| meanmail diff --git a/docs/utilities.rst b/docs/utilities.rst index a1d16e5c..99ee5601 100644 --- a/docs/utilities.rst +++ b/docs/utilities.rst @@ -328,9 +328,9 @@ FieldTracker implementation details This is how ``FieldTracker`` tracks field changes on ``instance.save`` call. -1. In ``class_prepared`` handler ``FieldTracker`` patches ``save_base`` and - ``refresh_from_db`` methods to reset initial state for tracked fields. -2. In ``post_init`` handler ``FieldTracker`` saves initial values for tracked +1. In ``class_prepared`` handler ``FieldTracker`` patches ``save_base``, + ``refresh_from_db`` and ``__init__`` methods to reset initial state for tracked fields. +2. In the patched ``__init__`` method ``FieldTracker`` saves initial values for tracked fields. 3. ``MyModel.save`` changes ``update_fields`` in order to store auto updated ``modified`` timestamp. Complete list of saved fields is now known. diff --git a/model_utils/tracker.py b/model_utils/tracker.py index c86b27e8..e2a96a71 100644 --- a/model_utils/tracker.py +++ b/model_utils/tracker.py @@ -343,7 +343,7 @@ def finalize_class(self, sender, **kwargs): wrapped_descriptor = wrapper_cls(field_name, descriptor, self.attname) setattr(sender, field_name, wrapped_descriptor) self.field_map = self.get_field_map(sender) - models.signals.post_init.connect(self.initialize_tracker) + self.patch_init(sender) self.model_class = sender setattr(sender, self.name, self) self.patch_save(sender) @@ -356,6 +356,16 @@ def initialize_tracker(self, sender, instance, **kwargs): tracker.set_saved_fields() 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): self._patch(model, 'save_base', 'update_fields') self._patch(model, 'refresh_from_db', 'fields') From 2bbbfcbfcacec380fb07f52a7175393d4cf28329 Mon Sep 17 00:00:00 2001 From: meanmail Date: Sun, 5 Feb 2023 13:41:14 +0400 Subject: [PATCH 2/2] Update changelog --- CHANGES.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 11d2c725..d4ad635e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,10 +1,15 @@ Changelog ========= +4.5.0 +----- + +- Don't use `post_init` signal for initialize tracker + 4.4.0 (2024-02-10) ------------------ -- Add support for `Python 3.11` +- Add support for `Python 3.11` - Add support for `Python 3.12` - Drop support for `Python 3.7` - Add support for `Django 4.2`