From ff3f8e55463359315607dd4a760bdd0cfe54cb58 Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Thu, 31 Mar 2016 15:26:11 +0100 Subject: [PATCH] Use all the fields to determine _id variants. Fixes #214 If a tracker is defined on an inherited model, where the parent has a ForeignKey, the tracker will now correctly determine that the field_map takes `fk` -> `fk_id` --- AUTHORS.rst | 1 + CHANGES.rst | 3 +++ model_utils/tests/models.py | 5 +++++ model_utils/tests/tests.py | 7 ++++++- model_utils/tracker.py | 4 ++-- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 1776b2b..bd9edba 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -22,6 +22,7 @@ Jeff Elmore Keryn Knight Matthew Schinckel Michael van Tellingen +Mike Bryant Mikhail Silonov Patryk Zawadzki Paul McLanahan diff --git a/CHANGES.rst b/CHANGES.rst index b8910a0..31df274 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,9 @@ master (unreleased) * Add support for Django 1.10. +* Track foreign keys on parent models properly when a tracker + is defined on a child model. Fixes GH-214. + 2.4 (2015-12-03) ---------------- diff --git a/model_utils/tests/models.py b/model_utils/tests/models.py index 6b82541..c77c034 100644 --- a/model_utils/tests/models.py +++ b/model_utils/tests/models.py @@ -246,6 +246,11 @@ class InheritedTracked(Tracked): name2 = models.CharField(max_length=20) +class InheritedTrackedFK(TrackedFK): + custom_tracker = FieldTracker(fields=['fk_id']) + custom_tracker_without_id = FieldTracker(fields=['fk']) + + class ModelTracked(models.Model): name = models.CharField(max_length=20) number = models.IntegerField() diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py index d32bf86..84e2dd6 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -26,7 +26,7 @@ from model_utils.tests.models import ( StatusPlainTuple, TimeFrame, Monitored, MonitorWhen, MonitorWhenEmpty, StatusManagerAdded, TimeFrameManagerAdded, SplitFieldAbstractParent, ModelTracked, ModelTrackedFK, ModelTrackedNotDefault, ModelTrackedMultiple, InheritedModelTracked, - Tracked, TrackedFK, TrackedNotDefault, TrackedNonFieldAttr, TrackedMultiple, + Tracked, TrackedFK, InheritedTrackedFK, TrackedNotDefault, TrackedNonFieldAttr, TrackedMultiple, InheritedTracked, StatusFieldDefaultFilled, StatusFieldDefaultNotFilled, InheritanceManagerTestChild3, StatusFieldChoicesName) @@ -1682,6 +1682,11 @@ class InheritedFieldTrackerTests(FieldTrackerTests): self.assertRaises(FieldError, self.tracker.has_changed, 'name2') +class FieldTrackerInheritedForeignKeyTests(FieldTrackerForeignKeyTests): + + tracked_class = InheritedTrackedFK + + class ModelTrackerTests(FieldTrackerTests): tracked_class = ModelTracked diff --git a/model_utils/tracker.py b/model_utils/tracker.py index be5a7ff..1c7d386 100644 --- a/model_utils/tracker.py +++ b/model_utils/tracker.py @@ -101,7 +101,7 @@ class FieldTracker(object): def get_field_map(self, cls): """Returns dict mapping fields names to model attribute names""" field_map = dict((field, field) for field in self.fields) - all_fields = dict((f.name, f.attname) for f in cls._meta.local_fields) + all_fields = dict((f.name, f.attname) for f in cls._meta.fields) field_map.update(**dict((k, v) for (k, v) in all_fields.items() if k in field_map)) return field_map @@ -113,7 +113,7 @@ class FieldTracker(object): def finalize_class(self, sender, **kwargs): if self.fields is None: - self.fields = (field.attname for field in sender._meta.local_fields) + self.fields = (field.attname for field in sender._meta.fields) self.fields = set(self.fields) self.field_map = self.get_field_map(sender) models.signals.post_init.connect(self.initialize_tracker)