Skip to content

Commit 08b4de7

Browse files
Make skip_history_when_saving work when creating a new object (#1262)
* Made skip_history_when_saving work when creating ...a model object - not just when updating an object. Also improved the docs on saving without creating historical records, and fixed an unrelated `PollWithManyToMany` instance being used in the assertions in the existing test for `skip_history_when_saving`. * Apply suggestions from code review Co-authored-by: Tim Schilling <[email protected]> * More docs suggestions from code review --------- Co-authored-by: Tim Schilling <[email protected]>
1 parent 2a2bec9 commit 08b4de7

File tree

4 files changed

+59
-24
lines changed

4 files changed

+59
-24
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Changes
44
Unreleased
55
----------
66

7+
- Made ``skip_history_when_saving`` work when creating an object - not just when
8+
updating an object (gh-1262)
79

810
3.7.0 (2024-05-29)
911
------------------

docs/querying_history.rst

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -175,30 +175,50 @@ model history.
175175
<Poll: Poll object as of 2010-10-25 18:04:13.814128>
176176
177177
178-
Save without a historical record
179-
--------------------------------
178+
Save without creating historical records
179+
----------------------------------------
180180

181-
If you want to save a model without a historical record, you can use the following:
181+
If you want to save model objects without triggering the creation of any historical
182+
records, you can do the following:
182183

183184
.. code-block:: python
184185
185-
class Poll(models.Model):
186-
question = models.CharField(max_length=200)
187-
history = HistoricalRecords()
186+
poll.skip_history_when_saving = True
187+
poll.save()
188+
# We recommend deleting the attribute afterward
189+
del poll.skip_history_when_saving
190+
191+
This also works when creating an object, but only when calling ``save()``:
192+
193+
.. code-block:: python
194+
195+
# Note that `Poll.objects.create()` is not called
196+
poll = Poll(question="Why?")
197+
poll.skip_history_when_saving = True
198+
poll.save()
199+
del poll.skip_history_when_saving
188200
189-
def save_without_historical_record(self, *args, **kwargs):
190-
self.skip_history_when_saving = True
191-
try:
192-
ret = self.save(*args, **kwargs)
193-
finally:
194-
del self.skip_history_when_saving
195-
return ret
201+
.. note::
202+
Historical records will always be created when calling the ``create()`` manager method.
196203

204+
Alternatively, call the ``save_without_historical_record()`` method on each object
205+
instead of ``save()``.
206+
This method is automatically added to a model when registering it for history-tracking
207+
(i.e. defining a ``HistoricalRecords`` manager field on the model),
208+
and it looks like this:
209+
210+
.. code-block:: python
197211
198-
poll = Poll(question='something')
199-
poll.save_without_historical_record()
212+
def save_without_historical_record(self, *args, **kwargs):
213+
self.skip_history_when_saving = True
214+
try:
215+
ret = self.save(*args, **kwargs)
216+
finally:
217+
del self.skip_history_when_saving
218+
return ret
200219
201-
Or disable history records for all models by putting following lines in your ``settings.py`` file:
220+
Or disable the creation of historical records for *all* models
221+
by adding the following line to your settings:
202222

203223
.. code-block:: python
204224

simple_history/models.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ def contribute_to_class(self, cls, name):
180180
def add_extra_methods(self, cls):
181181
def save_without_historical_record(self, *args, **kwargs):
182182
"""
183-
Save model without saving a historical record
183+
Save the model instance without creating a historical record.
184184
185-
Make sure you know what you're doing before you use this method.
185+
Make sure you know what you're doing before using this method.
186186
"""
187187
self.skip_history_when_saving = True
188188
try:
@@ -651,8 +651,9 @@ def get_meta_options(self, model):
651651
def post_save(self, instance, created, using=None, **kwargs):
652652
if not getattr(settings, "SIMPLE_HISTORY_ENABLED", True):
653653
return
654-
if not created and hasattr(instance, "skip_history_when_saving"):
654+
if hasattr(instance, "skip_history_when_saving"):
655655
return
656+
656657
if not kwargs.get("raw", False):
657658
self.create_historical_record(instance, created and "+" or "~", using=using)
658659

simple_history/tests/tests/test_models.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,21 +2424,21 @@ def test_m2m_relation(self):
24242424
self.assertEqual(self.poll.history.all()[0].places.count(), 0)
24252425
self.assertEqual(poll_2.history.all()[0].places.count(), 2)
24262426

2427-
def test_skip_history(self):
2427+
def test_skip_history_when_updating_an_object(self):
24282428
skip_poll = PollWithManyToMany.objects.create(
24292429
question="skip history?", pub_date=today
24302430
)
2431-
self.assertEqual(self.poll.history.all().count(), 1)
2432-
self.assertEqual(self.poll.history.all()[0].places.count(), 0)
2431+
self.assertEqual(skip_poll.history.all().count(), 1)
2432+
self.assertEqual(skip_poll.history.all()[0].places.count(), 0)
24332433

24342434
skip_poll.skip_history_when_saving = True
24352435

24362436
skip_poll.question = "huh?"
24372437
skip_poll.save()
24382438
skip_poll.places.add(self.place)
24392439

2440-
self.assertEqual(self.poll.history.all().count(), 1)
2441-
self.assertEqual(self.poll.history.all()[0].places.count(), 0)
2440+
self.assertEqual(skip_poll.history.all().count(), 1)
2441+
self.assertEqual(skip_poll.history.all()[0].places.count(), 0)
24422442

24432443
del skip_poll.skip_history_when_saving
24442444
place_2 = Place.objects.create(name="Place 2")
@@ -2448,6 +2448,18 @@ def test_skip_history(self):
24482448
self.assertEqual(skip_poll.history.all().count(), 2)
24492449
self.assertEqual(skip_poll.history.all()[0].places.count(), 2)
24502450

2451+
def test_skip_history_when_creating_an_object(self):
2452+
initial_poll_count = PollWithManyToMany.objects.count()
2453+
2454+
skip_poll = PollWithManyToMany(question="skip history?", pub_date=today)
2455+
skip_poll.skip_history_when_saving = True
2456+
skip_poll.save()
2457+
skip_poll.places.add(self.place)
2458+
2459+
self.assertEqual(skip_poll.history.count(), 0)
2460+
self.assertEqual(PollWithManyToMany.objects.count(), initial_poll_count + 1)
2461+
self.assertEqual(skip_poll.places.count(), 1)
2462+
24512463
@override_settings(SIMPLE_HISTORY_ENABLED=False)
24522464
def test_saving_with_disabled_history_doesnt_create_records(self):
24532465
# 1 from `setUp()`

0 commit comments

Comments
 (0)