diff --git a/easyaudit/signals/model_signals.py b/easyaudit/signals/model_signals.py index 3581edd..4f3dcb7 100644 --- a/easyaudit/signals/model_signals.py +++ b/easyaudit/signals/model_signals.py @@ -6,6 +6,7 @@ from django.contrib.auth.models import AnonymousUser from django.contrib.contenttypes.models import ContentType from django.core import serializers +from django.core.exceptions import ObjectDoesNotExist from django.db import transaction from django.db.models import signals from django.utils import timezone @@ -47,7 +48,7 @@ def should_audit(instance): # signals def pre_save(sender, instance, raw, using, update_fields, **kwargs): - """https://docs.djangoproject.com/es/1.10/ref/signals/#post-save""" + """https://docs.djangoproject.com/en/3.0/ref/signals/#pre-save""" if raw: # Return if loading Fixtures return @@ -65,7 +66,13 @@ def pre_save(sender, instance, raw, using, update_fields, **kwargs): if instance.pk is None: created = True else: - created = False + try: + old_model = sender.objects.get(pk=instance.pk) + created = False + except ObjectDoesNotExist: + # This can happen when a model is saved as part of a Transaction. It then has + # a pk set but is actually created. + created = True # created or updated? if not created: @@ -127,7 +134,7 @@ def crud_flow(): def post_save(sender, instance, created, raw, using, update_fields, **kwargs): - """https://docs.djangoproject.com/es/1.10/ref/signals/#post-save""" + """https://docs.djangoproject.com/en/3.0/ref/signals/#post-save""" if raw: # Return if loading Fixtures return diff --git a/easyaudit/tests/test_app/models.py b/easyaudit/tests/test_app/models.py index 98d88e7..c41ac34 100644 --- a/easyaudit/tests/test_app/models.py +++ b/easyaudit/tests/test_app/models.py @@ -1,4 +1,4 @@ -from django.db import models +from django.db import models, transaction class TestModel(models.Model): @@ -13,3 +13,15 @@ class TestForeignKey(models.Model): class TestM2M(models.Model): name = models.CharField(max_length=50) test_m2m = models.ManyToManyField(TestModel) + + +@transaction.atomic +def create_in_transaction(): + m = TestModel.objects.create(name='Transaction') + fk = TestForeignKey.objects.create(name='TransactionFK', test_fk=m) + m2m = TestM2M(name='TrasactionM2M') + m2m.save() + m2m.test_m2m.add(m) + m2m.save() + + return m diff --git a/easyaudit/tests/test_app/tests.py b/easyaudit/tests/test_app/tests.py index 2223be2..89419ef 100644 --- a/easyaudit/tests/test_app/tests.py +++ b/easyaudit/tests/test_app/tests.py @@ -10,9 +10,10 @@ from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType import bs4 -from test_app.models import TestModel, TestForeignKey, TestM2M +from test_app.models import TestModel, TestForeignKey, TestM2M, create_in_transaction from easyaudit.models import CRUDEvent from easyaudit.middleware.easyaudit import set_current_user, clear_request +from easyaudit.signals import model_signals TEST_USER_EMAIL = 'joe@example.com' @@ -84,6 +85,11 @@ def test_fake_update(self): obj.save() self.assertEqual(2, crud_event_qs.count()) + def test_transactions(self): + obj = create_in_transaction() + crud_event_qs = CRUDEvent.objects.filter(object_id=obj.id, content_type=ContentType.objects.get_for_model(obj)) + self.assertTrue(2, crud_event_qs.count()) + @override_settings(TEST=True) class TestMiddleware(TestCase): @@ -185,3 +191,16 @@ def test_request_event_admin_no_users(self): response = self.client.get(reverse('admin:easyaudit_requestevent_changelist')) self.assertEqual(200, response.status_code) filters = self._list_filters(response.content) + + +@override_settings(TEST=True) +class TestPreSave(TestCase): + def test_new_model_with_id(self): + obj = TestModel(name='Bob') + obj.pk = 123 + model_signals.pre_save(TestModel, obj, None, 'default', None) + + # No event must be registered in pre-save as this model isn't created yet. + crud_event_qs = CRUDEvent.objects.filter(object_id=obj.id, content_type=ContentType.objects.get_for_model(obj)) + self.assertEqual(crud_event_qs.count(), 0) +