diff --git a/AUTHORS.rst b/AUTHORS.rst index 21c822d2..2c875fe5 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -45,6 +45,7 @@ | Jannis Leidel | Javier Garcia Sogo | Jeff Elmore +| Joe Riddle | John Vandenberg | Jonathan Sundqvist | João Amaro diff --git a/CHANGES.rst b/CHANGES.rst index 3a0033dc..4cb100e1 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,6 +12,7 @@ To be released - Drop support for `Python 3.7` (GH-#545) - Swedish translation (GH-#561) - Use proper column name instead of attname (GH-#573) +- Fix `ValueError` when calling `prefetch_related` for tracked `ForeignKey` fields (Fixes GH-433) 4.3.1 (2022-11-15) ------------------ diff --git a/model_utils/tracker.py b/model_utils/tracker.py index 682ed293..c86b27e8 100644 --- a/model_utils/tracker.py +++ b/model_utils/tracker.py @@ -103,6 +103,9 @@ def __set__(self, instance, value): 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/test_fields/test_field_tracker.py b/tests/test_fields/test_field_tracker.py index 670e5878..90f23709 100644 --- a/tests/test_fields/test_field_tracker.py +++ b/tests/test_fields/test_field_tracker.py @@ -538,6 +538,29 @@ def test_custom_without_id(self): self.assertCurrent(fk=self.instance.fk_id) +class FieldTrackerForeignKeyPrefetchRelatedTests(FieldTrackerTestCase): + """Test that using `prefetch_related` on a tracked field does not raise a ValueError.""" + + fk_class = Tracked + tracked_class = TrackedFK + + def setUp(self): + model_tracked = self.fk_class.objects.create(name="", number=0) + self.instance = self.tracked_class.objects.create(fk=model_tracked) + + def test_default(self): + self.tracker = self.instance.tracker + self.assertIsNotNone(list(self.tracked_class.objects.prefetch_related("fk"))) + + def test_custom(self): + self.tracker = self.instance.custom_tracker + self.assertIsNotNone(list(self.tracked_class.objects.prefetch_related("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"))) + + class FieldTrackerTimeStampedTests(FieldTrackerTestCase): fk_class = Tracked