Skip to content

Commit 90ed021

Browse files
Allows nullable MonitorField to be populated on creation
1 parent af7c211 commit 90ed021

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ To be released
66
- Add support for `Python 3.13` (GH-#628)
77
- Add formal support for `Django 5.2` (GH-#641)
88
- Drop support for older versions than `Django 4.2`
9+
- Fixes MonitorField not updating on creation with `when` and `null=True`
910

1011
5.0.0 (2024-09-01)
1112
------------------

model_utils/fields.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,14 @@ def pre_save(self, model_instance: models.Model, add: bool) -> Any:
148148
value = now()
149149
previous = getattr(model_instance, self.monitor_attname, None)
150150
current = self.get_monitored_value(model_instance)
151-
if previous != current:
152-
if self.when is None or current in self.when:
153-
setattr(model_instance, self.attname, value)
154-
self._save_initial(model_instance.__class__, model_instance)
151+
152+
should_update = previous != current
153+
if self.when is not None:
154+
should_update = (should_update or add) and current in self.when
155+
156+
if should_update:
157+
setattr(model_instance, self.attname, value)
158+
self._save_initial(model_instance.__class__, model_instance)
155159
return super().pre_save(model_instance, add)
156160

157161
def deconstruct(self) -> tuple[str, str, Sequence[Any], dict[str, Any]]:

tests/models.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ class MonitorWhenEmpty(models.Model):
123123
name_changed = MonitorField(monitor="name", when=[])
124124

125125

126+
class MonitorWhenNullable(models.Model):
127+
name = models.CharField(max_length=25)
128+
name_changed = MonitorField(monitor="name", when=["Jose"], null=True)
129+
130+
126131
class DoubleMonitored(models.Model):
127132
name = models.CharField(max_length=25)
128133
name_changed = MonitorField(monitor="name")

tests/test_fields/test_monitor_field.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
from django.test import TestCase
77

88
from model_utils.fields import MonitorField
9-
from tests.models import DoubleMonitored, Monitored, MonitorWhen, MonitorWhenEmpty
9+
from tests.models import (
10+
DoubleMonitored,
11+
Monitored,
12+
MonitorWhen,
13+
MonitorWhenEmpty,
14+
MonitorWhenNullable,
15+
)
1016

1117

1218
class MonitorFieldTests(TestCase):
@@ -85,6 +91,23 @@ def test_double_save(self) -> None:
8591
self.assertEqual(self.instance.name_changed, changed)
8692

8793

94+
class MonitorWhenNullableFieldTests(TestCase):
95+
"""
96+
Will record changes only when name is 'Jose'
97+
"""
98+
def test_created_Jose(self) -> None:
99+
with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0, tzinfo=timezone.utc)):
100+
instance = MonitorWhenNullable(name='Jose')
101+
instance.save()
102+
self.assertEqual(instance.name_changed, datetime(2016, 1, 1, 12, 0, 0, tzinfo=timezone.utc))
103+
104+
def test_created_Charlie(self) -> None:
105+
with time_machine.travel(datetime(2016, 1, 1, 12, 0, 0, tzinfo=timezone.utc)):
106+
instance = MonitorWhenNullable(name='Charlie')
107+
instance.save()
108+
self.assertIsNone(instance.name_changed)
109+
110+
88111
class MonitorWhenEmptyFieldTests(TestCase):
89112
"""
90113
Monitor should never be updated id when is an empty list.

0 commit comments

Comments
 (0)