diff --git a/AUTHORS.rst b/AUTHORS.rst index bacbd67..2a26eeb 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -1,6 +1,7 @@ Alejandro Varas Alex Orange Andy Freeland +Bram Boogaard Carl Meyer Curtis Maloney Den Lesnov diff --git a/CHANGES.rst b/CHANGES.rst index 04b0d17..e69171f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,11 @@ CHANGES master (unreleased) ------------------- +* Keep track of deferred fields on model instance instead of on +FieldInstanceTracker instance. Accessing deferred fields for multiple instances +of a model from the same queryset fails in current release. + + 2.2 (2014.07.31) ---------------- diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py index 38150a8..bbacfd1 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -1485,13 +1485,13 @@ class FieldTrackerTests(FieldTrackerTestCase, FieldTrackerCommonTests): self.instance.number = 1 self.instance.save() item = list(self.tracked_class.objects.only('name').all())[0] - self.assertTrue(item.tracker.deferred_fields) + self.assertTrue(item._deferred_fields) self.assertEqual(item.tracker.previous('number'), None) - self.assertTrue('number' in item.tracker.deferred_fields) + self.assertTrue('number' in item._deferred_fields) self.assertEqual(item.number, 1) - self.assertTrue('number' not in item.tracker.deferred_fields) + self.assertTrue('number' not in item._deferred_fields) self.assertEqual(item.tracker.previous('number'), 1) self.assertFalse(item.tracker.has_changed('number')) @@ -1499,6 +1499,20 @@ class FieldTrackerTests(FieldTrackerTestCase, FieldTrackerCommonTests): self.assertTrue(item.tracker.has_changed('number')) +class FieldTrackerMultipleInstancesTests(TestCase): + + def test_with_deferred_fields_access_multiple(self): + instances = [ + Tracked.objects.create(pk=1, name='foo', number=1), + Tracked.objects.create(pk=2, name='bar', number=2) + ] + + queryset = Tracked.objects.only('id') + + for instance in queryset: + name = instance.name + + class FieldTrackedModelCustomTests(FieldTrackerTestCase, FieldTrackerCommonTests): diff --git a/model_utils/tracker.py b/model_utils/tracker.py index 6cb4355..be5a7ff 100644 --- a/model_utils/tracker.py +++ b/model_utils/tracker.py @@ -32,10 +32,10 @@ class FieldInstanceTracker(object): def current(self, fields=None): """Returns dict of current values for all tracked fields""" if fields is None: - if self.deferred_fields: + if self.instance._deferred_fields: fields = [ field for field in self.fields - if field not in self.deferred_fields + if field not in self.instance._deferred_fields ] else: fields = self.fields @@ -62,7 +62,7 @@ class FieldInstanceTracker(object): ) def init_deferred_fields(self): - self.deferred_fields = [] + self.instance._deferred_fields = [] if not self.instance._deferred: return @@ -70,7 +70,7 @@ class FieldInstanceTracker(object): def __get__(field, instance, owner): data = instance.__dict__ if data.get(field.field_name, field) is field: - self.deferred_fields.remove(field.field_name) + instance._deferred_fields.remove(field.field_name) value = super(DeferredAttributeTracker, field).__get__( instance, owner) self.saved_data[field.field_name] = deepcopy(value) @@ -79,7 +79,7 @@ class FieldInstanceTracker(object): for field in self.fields: field_obj = self.instance.__class__.__dict__.get(field) if isinstance(field_obj, DeferredAttribute): - self.deferred_fields.append(field) + self.instance._deferred_fields.append(field) # Django 1.4 model = None