diff --git a/easyaudit/migrations/0016_alter_crudevent_event_type.py b/easyaudit/migrations/0016_alter_crudevent_event_type.py new file mode 100644 index 00000000..23375110 --- /dev/null +++ b/easyaudit/migrations/0016_alter_crudevent_event_type.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.11 on 2022-01-10 16:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('easyaudit', '0015_auto_20201019_1217'), + ] + + operations = [ + migrations.AlterField( + model_name='crudevent', + name='event_type', + field=models.SmallIntegerField(choices=[(1, 'Create'), (2, 'Update'), (3, 'Delete'), (4, 'Many-to-Many Change'), (5, 'Reverse Many-to-Many Change'), (6, 'Many-to-Many Add'), (7, 'Reverse Many-to-Many Add'), (8, 'Many-to-Many Remove'), (9, 'Reverse Many-to-Many Remove'), (10, 'Many-to-Many Clear'), (11, 'Reverse Many-to-Many Clear')], verbose_name='Event type'), + ), + ] diff --git a/easyaudit/models.py b/easyaudit/models.py index f428c6f4..21bf0d61 100644 --- a/easyaudit/models.py +++ b/easyaudit/models.py @@ -14,6 +14,8 @@ class CRUDEvent(models.Model): M2M_ADD_REV = 7 M2M_REMOVE = 8 M2M_REMOVE_REV = 9 + M2M_CLEAR = 10 + M2M_CLEAR_REV = 11 TYPES = ( (CREATE, _('Create')), @@ -25,6 +27,8 @@ class CRUDEvent(models.Model): (M2M_ADD_REV, _('Reverse Many-to-Many Add')), (M2M_REMOVE, _('Many-to-Many Remove')), (M2M_REMOVE_REV, _('Reverse Many-to-Many Remove')), + (M2M_CLEAR, _('Many-to-Many Clear')), + (M2M_CLEAR_REV, _('Reverse Many-to-Many Clear')), ) event_type = models.SmallIntegerField(choices=TYPES, verbose_name=_('Event type')) diff --git a/easyaudit/signals/model_signals.py b/easyaudit/signals/model_signals.py index e5645c62..c5b9eb98 100644 --- a/easyaudit/signals/model_signals.py +++ b/easyaudit/signals/model_signals.py @@ -225,6 +225,8 @@ def m2m_changed(sender, instance, action, reverse, model, pk_set, using, **kwarg event_type = CRUDEvent.M2M_ADD_REV elif action == 'post_remove': event_type = CRUDEvent.M2M_REMOVE_REV + elif action == 'post_clear': + event_type = CRUDEvent.M2M_CLEAR_REV else: event_type = CRUDEvent.M2M_CHANGE_REV # just in case @@ -245,6 +247,8 @@ def m2m_changed(sender, instance, action, reverse, model, pk_set, using, **kwarg event_type = CRUDEvent.M2M_ADD elif action == 'post_remove': event_type = CRUDEvent.M2M_REMOVE + elif action == 'post_clear': + event_type = CRUDEvent.M2M_CLEAR else: event_type = CRUDEvent.M2M_CHANGE # just in case @@ -262,7 +266,10 @@ def m2m_changed(sender, instance, action, reverse, model, pk_set, using, **kwarg def crud_flow(): try: - changed_fields = json.dumps({get_m2m_field_name(model, instance): list(pk_set)}, cls=DjangoJSONEncoder) + if action == "post_clear": + changed_fields = [] + else: + changed_fields = json.dumps({get_m2m_field_name(model, instance): list(pk_set)}, cls=DjangoJSONEncoder) with transaction.atomic(using=DATABASE_ALIAS): crud_event = audit_logger.crud({ 'event_type': event_type, diff --git a/easyaudit/tests/test_app/tests.py b/easyaudit/tests/test_app/tests.py index 96568a32..2bc27b10 100644 --- a/easyaudit/tests/test_app/tests.py +++ b/easyaudit/tests/test_app/tests.py @@ -70,6 +70,16 @@ def test_m2m_model(self): data = json.loads(crud_event.object_json_repr)[0] self.assertEqual([str(d) for d in data['fields']['test_m2m']], [str(obj.id)]) + def test_m2m_clear(self): + obj = self.Model.objects.create() + obj_m2m = self.M2MModel(name='test') + obj_m2m.save() + obj_m2m.test_m2m.add(obj) + obj_m2m.test_m2m.clear() + crud_event = CRUDEvent.objects.filter(object_id=obj_m2m.id, content_type=ContentType.objects.get_for_model(obj_m2m))[0] + data = json.loads(crud_event.object_json_repr)[0] + self.assertEqual([str(d) for d in data['fields']['test_m2m']], []) + @override_settings(DJANGO_EASY_AUDIT_CRUD_EVENT_NO_CHANGED_FIELDS_SKIP=True) def test_update_skip_no_changed_fields(self): obj = self.Model.objects.create()