mirror of
https://github.com/Hopiu/django-model-utils.git
synced 2026-04-14 00:21:03 +00:00
Fix FieldTracker's has_changed (fixes gh-51)
The FieldTracker has_changed method no longer returns True for any input when the instance is unsaved and no longer raises a FieldError for fields after the first save. The original ModelTracker behavior is maintained.
This commit is contained in:
parent
d28f3860cf
commit
9dc3dacabf
2 changed files with 91 additions and 22 deletions
|
|
@ -10,7 +10,7 @@ from django.utils.six import text_type
|
|||
from django.core.exceptions import ImproperlyConfigured, FieldError
|
||||
from django.test import TestCase
|
||||
|
||||
from model_utils import Choices, FieldTracker, ModelTracker
|
||||
from model_utils import Choices, FieldTracker
|
||||
from model_utils.fields import get_excerpt, MonitorField, StatusField
|
||||
from model_utils.managers import QueryManager
|
||||
from model_utils.models import StatusModel, TimeFramedModel
|
||||
|
|
@ -686,11 +686,6 @@ class FieldTrackerTestCase(TestCase):
|
|||
|
||||
class FieldTrackerCommonTests(object):
|
||||
|
||||
def test_pre_save_has_changed(self):
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.instance.name = 'new age'
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
|
||||
def test_pre_save_previous(self):
|
||||
self.assertPrevious(name=None, number=None)
|
||||
self.instance.name = 'new age'
|
||||
|
|
@ -710,32 +705,39 @@ class FieldTrackerTests(FieldTrackerTestCase, FieldTrackerCommonTests):
|
|||
self.assertTrue(isinstance(self.tracked_class.tracker, FieldTracker))
|
||||
|
||||
def test_pre_save_changed(self):
|
||||
self.assertChanged(name=None, number=None, id=None)
|
||||
self.assertChanged(name=None)
|
||||
self.instance.name = 'new age'
|
||||
self.assertChanged(name=None, number=None, id=None)
|
||||
self.assertChanged(name=None)
|
||||
self.instance.number = 8
|
||||
self.assertChanged(name=None, number=None, id=None)
|
||||
self.assertChanged(name=None, number=None)
|
||||
self.instance.name = ''
|
||||
self.assertChanged(name=None, number=None, id=None)
|
||||
self.assertChanged(name=None, number=None)
|
||||
|
||||
def test_pre_save_has_changed(self):
|
||||
self.assertHasChanged(name=True, number=False)
|
||||
self.instance.name = 'new age'
|
||||
self.assertHasChanged(name=True, number=False)
|
||||
self.instance.number = 7
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
|
||||
def test_first_save(self):
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.assertHasChanged(name=True, number=False)
|
||||
self.assertPrevious(name=None, number=None)
|
||||
self.assertCurrent(name='', number=None, id=None)
|
||||
self.assertChanged(name=None, number=None, id=None)
|
||||
self.assertChanged(name=None)
|
||||
self.instance.name = 'retro'
|
||||
self.instance.number = 4
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.assertPrevious(name=None, number=None)
|
||||
self.assertCurrent(name='retro', number=4, id=None)
|
||||
self.assertChanged(name=None, number=None, id=None)
|
||||
self.assertChanged(name=None, number=None)
|
||||
# Django 1.4 doesn't have update_fields
|
||||
if django.VERSION >= (1, 5, 0):
|
||||
self.instance.save(update_fields=[])
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.assertPrevious(name=None, number=None)
|
||||
self.assertCurrent(name='retro', number=4, id=None)
|
||||
self.assertChanged(name=None, number=None, id=None)
|
||||
self.assertChanged(name=None, number=None)
|
||||
self.assertRaises(ValueError, self.instance.save,
|
||||
update_fields=['number'])
|
||||
|
||||
|
|
@ -813,6 +815,25 @@ class FieldTrackedModelCustomTests(FieldTrackerTestCase,
|
|||
self.instance.name = ''
|
||||
self.assertChanged(name=None)
|
||||
|
||||
def test_first_save(self):
|
||||
self.assertHasChanged(name=True, number=None)
|
||||
self.assertPrevious(name=None, number=None)
|
||||
self.assertCurrent(name='')
|
||||
self.assertChanged(name=None)
|
||||
self.instance.name = 'retro'
|
||||
self.instance.number = 4
|
||||
self.assertHasChanged(name=True, number=None)
|
||||
self.assertPrevious(name=None, number=None)
|
||||
self.assertCurrent(name='retro')
|
||||
self.assertChanged(name=None)
|
||||
|
||||
def test_pre_save_has_changed(self):
|
||||
self.assertHasChanged(name=True, number=None)
|
||||
self.instance.name = 'new age'
|
||||
self.assertHasChanged(name=True, number=None)
|
||||
self.instance.number = 7
|
||||
self.assertHasChanged(name=True, number=None)
|
||||
|
||||
def test_post_save_has_changed(self):
|
||||
self.update_instance(name='retro', number=4)
|
||||
self.assertHasChanged(name=False, number=None)
|
||||
|
|
@ -858,11 +879,6 @@ class FieldTrackedModelMultiTests(FieldTrackerTestCase,
|
|||
self.trackers = [self.instance.name_tracker,
|
||||
self.instance.number_tracker]
|
||||
|
||||
def test_pre_save_has_changed(self):
|
||||
for tracker in self.trackers:
|
||||
self.tracker = tracker
|
||||
super(FieldTrackedModelMultiTests, self).test_pre_save_has_changed()
|
||||
|
||||
def test_pre_save_changed(self):
|
||||
self.tracker = self.instance.name_tracker
|
||||
self.assertChanged(name=None)
|
||||
|
|
@ -879,6 +895,16 @@ class FieldTrackedModelMultiTests(FieldTrackerTestCase,
|
|||
self.instance.number = 8
|
||||
self.assertChanged(number=None)
|
||||
|
||||
def test_pre_save_has_changed(self):
|
||||
self.tracker = self.instance.name_tracker
|
||||
self.assertHasChanged(name=True, number=None)
|
||||
self.instance.name = 'new age'
|
||||
self.assertHasChanged(name=True, number=None)
|
||||
self.tracker = self.instance.number_tracker
|
||||
self.assertHasChanged(name=None, number=False)
|
||||
self.instance.name = 'new age'
|
||||
self.assertHasChanged(name=None, number=False)
|
||||
|
||||
def test_pre_save_previous(self):
|
||||
for tracker in self.trackers:
|
||||
self.tracker = tracker
|
||||
|
|
@ -1011,11 +1037,37 @@ class ModelTrackerTests(FieldTrackerTests):
|
|||
self.assertRaises(ValueError, self.instance.save,
|
||||
update_fields=['number'])
|
||||
|
||||
def test_pre_save_has_changed(self):
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.instance.name = 'new age'
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.instance.number = 7
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
|
||||
|
||||
class ModelTrackedModelCustomTests(FieldTrackedModelCustomTests):
|
||||
|
||||
tracked_class = ModelTrackedNotDefault
|
||||
|
||||
def test_first_save(self):
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.assertPrevious(name=None, number=None)
|
||||
self.assertCurrent(name='')
|
||||
self.assertChanged()
|
||||
self.instance.name = 'retro'
|
||||
self.instance.number = 4
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.assertPrevious(name=None, number=None)
|
||||
self.assertCurrent(name='retro')
|
||||
self.assertChanged()
|
||||
|
||||
def test_pre_save_has_changed(self):
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.instance.name = 'new age'
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.instance.number = 7
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
|
||||
def test_pre_save_changed(self):
|
||||
self.assertChanged()
|
||||
self.instance.name = 'new age'
|
||||
|
|
@ -1030,6 +1082,16 @@ class ModelTrackedModelMultiTests(FieldTrackedModelMultiTests):
|
|||
|
||||
tracked_class = ModelTrackedMultiple
|
||||
|
||||
def test_pre_save_has_changed(self):
|
||||
self.tracker = self.instance.name_tracker
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.instance.name = 'new age'
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.tracker = self.instance.number_tracker
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
self.instance.name = 'new age'
|
||||
self.assertHasChanged(name=True, number=True)
|
||||
|
||||
def test_pre_save_changed(self):
|
||||
self.tracker = self.instance.name_tracker
|
||||
self.assertChanged()
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ class FieldInstanceTracker(object):
|
|||
|
||||
def has_changed(self, field):
|
||||
"""Returns ``True`` if field has changed from currently saved value"""
|
||||
if not self.instance.pk:
|
||||
return True
|
||||
elif field in self.saved_data:
|
||||
if field in self.fields:
|
||||
return self.previous(field) != self.get_field_value(field)
|
||||
else:
|
||||
raise FieldError('field "%s" not tracked' % field)
|
||||
|
|
@ -98,6 +96,15 @@ class FieldTracker(object):
|
|||
|
||||
class ModelInstanceTracker(FieldInstanceTracker):
|
||||
|
||||
def has_changed(self, field):
|
||||
"""Returns ``True`` if field has changed from currently saved value"""
|
||||
if not self.instance.pk:
|
||||
return True
|
||||
elif field in self.saved_data:
|
||||
return self.previous(field) != self.get_field_value(field)
|
||||
else:
|
||||
raise FieldError('field "%s" not tracked' % field)
|
||||
|
||||
def changed(self):
|
||||
"""Returns dict of fields that changed since save (with old values)"""
|
||||
if not self.instance.pk:
|
||||
|
|
|
|||
Loading…
Reference in a new issue