diff --git a/model_utils/tracker.py b/model_utils/tracker.py index 682ed29..c86b27e 100644 --- a/model_utils/tracker.py +++ b/model_utils/tracker.py @@ -103,6 +103,9 @@ class DescriptorWrapper: else: instance.__dict__[self.field_name] = value + def __getattr__(self, attr): + return getattr(self.descriptor, attr) + @staticmethod def cls_for_descriptor(descriptor): if hasattr(descriptor, '__delete__'): diff --git a/tests/models.py b/tests/models.py index d785e88..adbf344 100644 --- a/tests/models.py +++ b/tests/models.py @@ -324,6 +324,14 @@ class ModelTrackedFK(models.Model): custom_tracker_without_id = ModelTracker(fields=['fk']) +class ModelTrackedPrefetchRelatedFK(models.Model): + fk = models.ForeignKey('ModelTrackedFK', on_delete=models.CASCADE) + + tracker = ModelTracked() + custom_tracker = ModelTracker(fields=['fk_id']) + custom_tracker_without_id = ModelTracker(fields=['fk']) + + class ModelTrackedNotDefault(models.Model): name = models.CharField(max_length=20) number = models.IntegerField() diff --git a/tests/test_fields/test_field_tracker.py b/tests/test_fields/test_field_tracker.py index 670e587..77f3ea0 100644 --- a/tests/test_fields/test_field_tracker.py +++ b/tests/test_fields/test_field_tracker.py @@ -15,6 +15,7 @@ from tests.models import ( ModelTrackedFK, ModelTrackedMultiple, ModelTrackedNotDefault, + ModelTrackedPrefetchRelatedFK, Tracked, TrackedAbstract, TrackedFileField, @@ -538,6 +539,29 @@ class FieldTrackerForeignKeyTests(FieldTrackerTestCase): self.assertCurrent(fk=self.instance.fk_id) +class ModelTrackedPrefetchRelatedFKTests(FieldTrackerTestCase): + """Test that using `prefetch_related` on a tracked field does raise a ValueError.""" + + tracked_class = ModelTrackedPrefetchRelatedFK + + def setUp(self): + model_tracked = ModelTracked.objects.create(name="", number=0) + model_tracked_fk = ModelTrackedFK.objects.create(fk=model_tracked) + self.instance = ModelTrackedPrefetchRelatedFK.objects.create(fk=model_tracked_fk) + + def test_default(self): + self.tracker = self.instance.tracker + self.assertIsNotNone(list(self.tracked_class.objects.prefetch_related("fk__fk"))) + + def test_custom(self): + self.tracker = self.instance.custom_tracker + self.assertIsNotNone(list(self.tracked_class.objects.prefetch_related("fk__fk"))) + + def test_custom_without_id(self): + self.tracker = self.instance.custom_tracker_without_id + self.assertIsNotNone(list(self.tracked_class.objects.prefetch_related("fk__fk"))) + + class FieldTrackerTimeStampedTests(FieldTrackerTestCase): fk_class = Tracked