fix: defer field deletion error in auditlog

This commit is contained in:
Tosinibikunle 2025-08-20 15:53:04 +01:00
parent 8003b069c9
commit 99847e5d40
2 changed files with 35 additions and 0 deletions

View file

@ -240,7 +240,19 @@ class LogEntryManager(models.Manager):
"fields", self._get_applicable_model_fields(instance, model_fields)
)
# safeguard: if fields explicitly set → only use them
if "fields" in kwargs:
allowed_fields = set(kwargs["fields"])
else:
allowed_fields = {f.name for f in instance._meta.fields}
instance_copy = self._get_copy_with_python_typed_fields(instance)
# drop any deferred field not in allowed_fields
for f in instance_copy._meta.fields:
if f.name not in allowed_fields and f.name in getattr(instance_copy, "deferred_fields", []):
setattr(instance_copy, f.name, None)
data = dict(
json.loads(serializers.serialize("json", (instance_copy,), **kwargs))[0]
)
@ -251,6 +263,7 @@ class LogEntryManager(models.Manager):
return data
def _get_copy_with_python_typed_fields(self, instance):
"""
Attempt to create copy of instance and coerce types on instance fields

View file

@ -25,6 +25,7 @@ from django.urls import resolve, reverse
from django.utils import dateformat, formats
from django.utils import timezone as django_timezone
from django.utils.encoding import smart_str
from django.test.utils import isolate_apps
from django.utils.translation import gettext_lazy as _
from test_app.fixtures.custom_get_cid import get_cid as custom_get_cid
from test_app.models import (
@ -123,6 +124,27 @@ class SimpleModelTest(TestCase):
msg="The change is correctly logged",
)
@isolate_apps("auditlog_tests")
def test_deletion_with_deferred_fields_does_not_crash(db):
from auditlog.models import LogEntry
from auditlog.registry import auditlog
class Book(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
class Meta:
app_label = "auditlog_tests"
auditlog.register(Book, serialize_data=True)
b = Book.objects.create(title="foo", description="bar")
b = Book.objects.defer("description").get(id=b.id) # defer a field
b.delete()
assert LogEntry.objects.filter(object_pk=b.pk).exists()
def test_update_specific_field_supplied_via_save_method(self):
obj = self.obj