From fb1ae7abedaa2b4b39cff8297b8ada86e514ff08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleh=20Ryma=C5=A1e=C5=ADski?= Date: Thu, 24 Aug 2023 15:25:56 +0000 Subject: [PATCH] Set history delete_related to False by default (#557) This is a breaking change. The default behavior is to delete the related objects, but it doesn't make sense to apply it to audit log entries, at least not by default. --- CHANGELOG.md | 1 + auditlog/models.py | 8 +++----- auditlog_tests/models.py | 32 ++++++++++++++++---------------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73a3569..8a6028b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - feat: Change `LogEntry.change` field type to `JSONField` rather than `TextField`. This change include a migration that may take time to run depending on the number of records on your `LogEntry` table ([#407](https://github.com/jazzband/django-auditlog/pull/407))([#495](https://github.com/jazzband/django-auditlog/pull/495)) - Python: Drop support for Python 3.7 ([#546](https://github.com/jazzband/django-auditlog/pull/546)) +- feat: Set `AuditlogHistoryField.delete_related` to `False` by default. This is different from the default configuration of Django's `GenericRelation`, but we should not erase the audit log of objects on deletion by default. ([#557](https://github.com/jazzband/django-auditlog/pull/557)) #### Improvements diff --git a/auditlog/models.py b/auditlog/models.py index 23ba144..3df0b63 100644 --- a/auditlog/models.py +++ b/auditlog/models.py @@ -557,14 +557,12 @@ class AuditlogHistoryField(GenericRelation): :param pk_indexable: Whether the primary key for this model is not an :py:class:`int` or :py:class:`long`. :type pk_indexable: bool - :param delete_related: By default, including a generic relation into a model will cause all related - objects to be cascade-deleted when the parent object is deleted. Passing False to this overrides this - behavior, retaining the full auditlog history for the object. Defaults to True, because that's - Django's default behavior. + :param delete_related: Delete referenced auditlog entries together with the tracked object. + Defaults to False to keep the integrity of the auditlog. :type delete_related: bool """ - def __init__(self, pk_indexable=True, delete_related=True, **kwargs): + def __init__(self, pk_indexable=True, delete_related=False, **kwargs): kwargs["to"] = LogEntry if pk_indexable: diff --git a/auditlog_tests/models.py b/auditlog_tests/models.py index 1d454a8..04736a0 100644 --- a/auditlog_tests/models.py +++ b/auditlog_tests/models.py @@ -21,7 +21,7 @@ class SimpleModel(models.Model): integer = models.IntegerField(blank=True, null=True) datetime = models.DateTimeField(auto_now=True) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) def __str__(self): return self.text @@ -39,7 +39,7 @@ class AltPrimaryKeyModel(models.Model): integer = models.IntegerField(blank=True, null=True) datetime = models.DateTimeField(auto_now=True) - history = AuditlogHistoryField(pk_indexable=False) + history = AuditlogHistoryField(delete_related=True, pk_indexable=False) class UUIDPrimaryKeyModel(models.Model): @@ -54,7 +54,7 @@ class UUIDPrimaryKeyModel(models.Model): integer = models.IntegerField(blank=True, null=True) datetime = models.DateTimeField(auto_now=True) - history = AuditlogHistoryField(pk_indexable=False) + history = AuditlogHistoryField(delete_related=True, pk_indexable=False) class ProxyModel(SimpleModel): @@ -84,7 +84,7 @@ class RelatedModel(RelatedModelParent): to="SimpleModel", on_delete=models.CASCADE, related_name="reverse_one_to_one" ) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) class ManyRelatedModel(models.Model): @@ -95,7 +95,7 @@ class ManyRelatedModel(models.Model): recursive = models.ManyToManyField("self") related = models.ManyToManyField("ManyRelatedOtherModel", related_name="related") - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) def get_additional_data(self): related = self.related.first() @@ -107,7 +107,7 @@ class ManyRelatedOtherModel(models.Model): A model related to ManyRelatedModel as many-to-many. """ - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) @auditlog.register(include_fields=["label"]) @@ -119,7 +119,7 @@ class SimpleIncludeModel(models.Model): label = models.CharField(max_length=100) text = models.TextField(blank=True) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) class SimpleExcludeModel(models.Model): @@ -130,7 +130,7 @@ class SimpleExcludeModel(models.Model): label = models.CharField(max_length=100) text = models.TextField(blank=True) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) class SimpleMappingModel(models.Model): @@ -142,7 +142,7 @@ class SimpleMappingModel(models.Model): vtxt = models.CharField(verbose_name="Version", max_length=100) not_mapped = models.CharField(max_length=100) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) @auditlog.register(mask_fields=["address"]) @@ -154,7 +154,7 @@ class SimpleMaskedModel(models.Model): address = models.CharField(max_length=100) text = models.TextField() - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) class AdditionalDataIncludedModel(models.Model): @@ -167,7 +167,7 @@ class AdditionalDataIncludedModel(models.Model): text = models.TextField(blank=True) related = models.ForeignKey(to=SimpleModel, on_delete=models.CASCADE) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) def get_additional_data(self): """ @@ -194,7 +194,7 @@ class DateTimeFieldModel(models.Model): time = models.TimeField() naive_dt = models.DateTimeField(null=True, blank=True) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) class ChoicesFieldModel(models.Model): @@ -216,7 +216,7 @@ class ChoicesFieldModel(models.Model): status = models.CharField(max_length=1, choices=STATUS_CHOICES) multiplechoice = models.CharField(max_length=255, choices=STATUS_CHOICES) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) class CharfieldTextfieldModel(models.Model): @@ -229,7 +229,7 @@ class CharfieldTextfieldModel(models.Model): longchar = models.CharField(max_length=255) longtextfield = models.TextField() - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) class PostgresArrayFieldModel(models.Model): @@ -251,7 +251,7 @@ class PostgresArrayFieldModel(models.Model): models.CharField(max_length=1, choices=STATUS_CHOICES), size=3 ) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) class NoDeleteHistoryModel(models.Model): @@ -314,7 +314,7 @@ class SimpleNonManagedModel(models.Model): integer = models.IntegerField(blank=True, null=True) datetime = models.DateTimeField(auto_now=True) - history = AuditlogHistoryField() + history = AuditlogHistoryField(delete_related=True) def __str__(self): return self.text