diff --git a/AUTHORS.rst b/AUTHORS.rst index c86a15d..3445921 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -15,6 +15,7 @@ | Bo Marchman | Bojan Mihelac | Bruno Alla +| Bugra Aydin | Craig Anderson | Daniel Andrlik | Daniel Stanton diff --git a/CHANGES.rst b/CHANGES.rst index 25c45ff..153d5be 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -13,6 +13,9 @@ CHANGES - Add available_objects manager to SoftDeletableModel and add deprecation warning to objects manager. - Add support for `Django 3.1` +- StatusModel now automatically adds 'status_changed' field during save as an + update_fieldsparameter when 'status' is present in it to make sure it is not + forgotten. 4.0.0 (2019-12-11) ------------------ diff --git a/model_utils/models.py b/model_utils/models.py index afec145..fdf13a2 100644 --- a/model_utils/models.py +++ b/model_utils/models.py @@ -67,6 +67,20 @@ class StatusModel(models.Model): status = StatusField(_('status')) status_changed = MonitorField(_('status changed'), monitor='status') + def save(self, *args, **kwargs): + """ + Overriding the save method in order to make sure that + status_changed field is updated even if it is not given as + a parameter to the update field argument. + """ + if ( + 'update_fields' in kwargs + and 'status' in kwargs['update_fields'] + and 'status_changed' not in kwargs['update_fields'] + ): + kwargs['update_fields'] += ['status_changed'] + super().save(*args, **kwargs) + class Meta: abstract = True diff --git a/tests/test_models/test_status_model.py b/tests/test_models/test_status_model.py index 6950dbf..1e8d534 100644 --- a/tests/test_models/test_status_model.py +++ b/tests/test_models/test_status_model.py @@ -38,6 +38,36 @@ class StatusModelTests(TestCase): t1.save() self.assertTrue(t1.status_changed > date_active_again) + def test_save_with_update_fields_overrides_status_changed_provided(self): + ''' + Tests if the save method updated status_changed field + accordingly when update_fields is used as an argument + and status_changed is provided + ''' + with freeze_time(datetime(2020,1,1)): + t1 = Status.objects.create() + + with freeze_time(datetime(2020,1,2)): + t1.status = Status.on_hold + t1.save(update_fields=['status', 'status_changed']) + + self.assertEqual(t1.status_changed, datetime(2020,1,2)) + + def test_save_with_update_fields_overrides_status_changed_not_provided(self): + ''' + Tests if the save method updated status_changed field + accordingly when update_fields is used as an argument + with status and status_changed is not provided + ''' + with freeze_time(datetime(2020,1,1)): + t1 = Status.objects.create() + + with freeze_time(datetime(2020,1,2)): + t1.status = Status.on_hold + t1.save(update_fields=['status']) + + self.assertEqual(t1.status_changed, datetime(2020,1,2)) + class StatusModelPlainTupleTests(StatusModelTests): def setUp(self):