diff --git a/CHANGES.rst b/CHANGES.rst index b6759da..3d9bb66 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,8 @@ master (unreleased) ``update_fields`` in which there are untracked fields. Thanks Mikhail Silonov. (Merge of GH-70, fixes GH-71). +* Fixed ``FieldTracker`` usage on inherited models. Fixes GH-57. + 1.4.0 (2013.06.03) ------------------ diff --git a/model_utils/tests/models.py b/model_utils/tests/models.py index 99d33ad..06b3dea 100644 --- a/model_utils/tests/models.py +++ b/model_utils/tests/models.py @@ -271,6 +271,10 @@ class TrackedMultiple(models.Model): number_tracker = FieldTracker(fields=['number']) +class InheritedTracked(Tracked): + name2 = models.CharField(max_length=20) + + class ModelTracked(models.Model): name = models.CharField(max_length=20) number = models.IntegerField() @@ -300,6 +304,9 @@ class ModelTrackedMultiple(models.Model): name_tracker = ModelTracker(fields=['name']) number_tracker = ModelTracker(fields=['number']) +class InheritedModelTracked(ModelTracked): + name2 = models.CharField(max_length=20) + class StatusFieldDefaultFilled(models.Model): STATUS = Choices((0, "no", "No"), (1, "yes", "Yes")) diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py index 01827b8..04dfb60 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -25,9 +25,9 @@ from model_utils.tests.models import ( InheritanceManagerTestChild2, TimeStamp, Post, Article, Status, StatusPlainTuple, TimeFrame, Monitored, StatusManagerAdded, TimeFrameManagerAdded, Dude, SplitFieldAbstractParent, Car, Spot, - ModelTracked, ModelTrackedFK, ModelTrackedNotDefault, ModelTrackedMultiple, + ModelTracked, ModelTrackedFK, ModelTrackedNotDefault, ModelTrackedMultiple, InheritedModelTracked, Tracked, TrackedFK, TrackedNotDefault, TrackedNonFieldAttr, - TrackedMultiple, StatusFieldDefaultFilled, StatusFieldDefaultNotFilled) + TrackedMultiple, InheritedTracked, StatusFieldDefaultFilled, StatusFieldDefaultNotFilled) @@ -1114,6 +1114,16 @@ class FieldTrackerForeignKeyTests(FieldTrackerTestCase): self.assertCurrent(fk=self.instance.fk_id) +class InheritedFieldTrackerTests(FieldTrackerTests): + + tracked_class = InheritedTracked + + def test_child_fields_not_tracked(self): + self.name2 = 'test' + self.assertEqual(self.tracker.previous('name2'), None) + self.assertRaises(FieldError, self.tracker.has_changed, 'name2') + + class ModelTrackerTests(FieldTrackerTests): tracked_class = ModelTracked @@ -1237,3 +1247,13 @@ class ModelTrackerForeignKeyTests(FieldTrackerForeignKeyTests): self.assertChanged(fk=self.old_fk) self.assertPrevious(fk=self.old_fk) self.assertCurrent(fk=self.instance.fk) + + +class InheritedModelTrackerTests(ModelTrackerTests): + + tracked_class = InheritedModelTracked + + def test_child_fields_not_tracked(self): + self.name2 = 'test' + self.assertEqual(self.tracker.previous('name2'), None) + self.assertTrue(self.tracker.has_changed('name2')) diff --git a/model_utils/tracker.py b/model_utils/tracker.py index aecf27c..6c29bc0 100644 --- a/model_utils/tracker.py +++ b/model_utils/tracker.py @@ -71,10 +71,13 @@ class FieldTracker(object): self.fields = (field.attname for field in sender._meta.local_fields) self.fields = set(self.fields) self.field_map = self.get_field_map(sender) - models.signals.post_init.connect(self.initialize_tracker, sender=sender) + models.signals.post_init.connect(self.initialize_tracker) + self.model_class = sender setattr(sender, self.name, self) def initialize_tracker(self, sender, instance, **kwargs): + if not isinstance(instance, self.model_class): + return # Only init instances of given model (including children) tracker = self.tracker_class(instance, self.fields, self.field_map) setattr(instance, self.attname, tracker) tracker.set_saved_fields()