From ce6ef4d3c5be76fca9d63f3d6202f218b73175b3 Mon Sep 17 00:00:00 2001 From: knokko Date: Thu, 4 Apr 2024 14:22:45 +0200 Subject: [PATCH] Dont put auto_now and auto_now_add fields in the history --- binder/history.py | 22 ++++++++++++++++++++-- tests/test_history.py | 20 ++++++++++++++++++++ tests/testapp/models/contact_person.py | 3 +++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/binder/history.py b/binder/history.py index 698f9377..3137cb80 100644 --- a/binder/history.py +++ b/binder/history.py @@ -7,6 +7,7 @@ from django.contrib.auth import get_user_model from django.conf import settings from django.dispatch import Signal +from django.core.exceptions import FieldDoesNotExist from .json import jsondumps, JsonResponse @@ -172,7 +173,18 @@ def _commit(): ) changeset.save() + auto_now_counter = 0 + for (model, oid, field), (old, new, diff) in _Transaction.changes.items(): + + # Skip auto_now and auto_now_add fields because they are not interesting for the history + try: + field_properties = model._meta.get_field(field) + if field_properties.auto_now or field_properties.auto_now_add: + auto_now_counter += 1 + except (FieldDoesNotExist, AttributeError): + pass + # New instances get None for all the before values if old is NewInstanceField: old = None @@ -191,8 +203,14 @@ def _commit(): transaction_commit.send(sender=None, changeset=changeset) - # Save the changeset again, to update the date to be as close to DB transaction commit start as possible. - changeset.save() + if changeset.changes.count() > auto_now_counter: + # Save the changeset again, to update the date to be as close to DB transaction commit start as possible. + changeset.save() + else: + # Changesets without real changes are useless + changeset.changes.all().delete() + changeset.delete() + _Transaction.stop() diff --git a/tests/test_history.py b/tests/test_history.py index 00464d95..a792fed6 100644 --- a/tests/test_history.py +++ b/tests/test_history.py @@ -80,7 +80,27 @@ def test_model_with_history_creates_changes_on_creation(self): self.assertEqual(1, Change.objects.filter(changeset=cs, model='Animal', field='deleted', before='null', after='false').count()) self.assertEqual(1, Change.objects.filter(changeset=cs, model='Animal', field='birth_date', before='null', after='null').count()) + def test_do_not_keep_auto_now_only_changesets(self): + tim = ContactPerson.objects.create(name="Tim") + self.assertEqual(0, Changeset.objects.count()) + self.assertEqual(0, Change.objects.count()) + + self.assertEqual(self.client.patch( + '/contact_person/%d/' % tim.pk, data=json.dumps({'name': 'Tim'}), content_type='application/json' + ).status_code, 200) + + self.assertEqual(0, Change.objects.count()) + self.assertEqual(0, Changeset.objects.count()) + + self.assertEqual(self.client.patch( + '/contact_person/%d/' % tim.pk, data=json.dumps({'name': 'knokko'}), content_type='application/json' + ).status_code, 200) + + self.assertEqual(2, Change.objects.count()) + self.assertEqual(1, Changeset.objects.count()) + self.assertEqual(1, Change.objects.filter(model='ContactPerson', after='"knokko"').count()) + self.assertEqual(1, Change.objects.filter(model='ContactPerson', field='updated_at').count()) def test_model_with_history_creates_changes_on_update_but_only_for_changed_fields(self): daffy = Animal(name='Daffy Duck') diff --git a/tests/testapp/models/contact_person.py b/tests/testapp/models/contact_person.py index 60db9897..241ee971 100644 --- a/tests/testapp/models/contact_person.py +++ b/tests/testapp/models/contact_person.py @@ -7,6 +7,9 @@ class ContactPerson(BinderModel): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) + class Binder: + history = True + def __str__(self): return 'contact_person %d: %s' % (self.pk, self.name)