This commit is contained in:
Tosinibikunle 2025-12-04 01:28:55 +09:00 committed by GitHub
commit 518ac4d6ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 23 additions and 28 deletions

View file

@ -2,6 +2,13 @@
## Next Release
## (2025-08-14)
### Fixes
- fix: Ensure `object_pk` lookup works for non-string primary keys by casting PK to string in `get_for_object()` and related queries.
- fix: Updated tests to correctly match log entries for integer, UUID, or string primary keys. ([#746](https://github.com/jazzband/django-auditlog/pull/746))
#### Improvements
- feat: Add `AUDITLOG_USE_FK_STRING_REPRESENTATION` setting that controls how foreign key changes are represented ([#779)](https://github.com/jazzband/django-auditlog/pull/779))

View file

@ -4,6 +4,7 @@ from django import urls as urlresolvers
from django.conf import settings
from django.contrib import admin
from django.contrib.admin.views.main import PAGE_VAR
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.http import HttpRequest
from django.template.response import TemplateResponse
@ -139,9 +140,11 @@ class AuditlogHistoryAdminMixin:
obj = self.get_object(request, unquote(object_id))
if not self.has_view_permission(request, obj):
raise PermissionDenied
ct = ContentType.objects.get_for_model(obj.__class__)
log_entries = (
LogEntry.objects.get_for_object(obj)
LogEntry.objects.filter(
content_type=ct, object_pk=str(obj.pk)
) # <--- Fixed here
.select_related("actor")
.order_by("-timestamp")
)

View file

@ -148,10 +148,7 @@ class LogEntryManager(models.Manager):
content_type = ContentType.objects.get_for_model(instance.__class__)
pk = self._get_pk_value(instance)
if isinstance(pk, int):
return self.filter(content_type=content_type, object_id=pk)
else:
return self.filter(content_type=content_type, object_pk=smart_str(pk))
return self.filter(content_type=content_type, object_pk=smart_str(pk))
def get_for_objects(self, queryset):
"""
@ -160,8 +157,7 @@ class LogEntryManager(models.Manager):
:param queryset: The queryset to get the log entries for.
:type queryset: QuerySet
:return: The LogEntry objects for the objects in the given queryset.
:rtype: QuerySet
"""
:rtype: QuerySet"""
if not isinstance(queryset, QuerySet) or queryset.count() == 0:
return self.none()
@ -170,25 +166,14 @@ class LogEntryManager(models.Manager):
queryset.values_list(queryset.model._meta.pk.name, flat=True)
)
if isinstance(primary_keys[0], int):
return (
self.filter(content_type=content_type)
.filter(Q(object_id__in=primary_keys))
.distinct()
)
elif isinstance(queryset.model._meta.pk, models.UUIDField):
primary_keys = [smart_str(pk) for pk in primary_keys]
return (
self.filter(content_type=content_type)
.filter(Q(object_pk__in=primary_keys))
.distinct()
)
else:
return (
self.filter(content_type=content_type)
.filter(Q(object_pk__in=primary_keys))
.distinct()
)
# Always compare as strings for PostgreSQL compatibility
primary_keys = [smart_str(pk) for pk in primary_keys]
return (
self.filter(content_type=content_type)
.filter(Q(object_pk__in=primary_keys))
.distinct()
)
def get_for_model(self, model):
"""

View file

@ -191,7 +191,7 @@ class SimpleModelTest(TestCase):
self.delete(obj)
# Check for log entries
qs = LogEntry.objects.filter(content_type=content_type, object_pk=pk)
qs = LogEntry.objects.filter(content_type=content_type, object_pk=str(pk))
self.assertEqual(qs.count(), 1, msg="There is one log entry for 'DELETE'")
history = qs.get()