Support models with UUID primary keys (#111)

Fixes #110 to add support for UUID primary keys in related many to many querysets in the `get_for_objects()` method.

Forces queryset evaluation in `get_for_objects()` to cache the queryset, reducing additional db queries.
This commit is contained in:
Grant McConnaughey 2017-06-29 09:19:33 -05:00 committed by Ryan Castner
parent 511816afc2
commit cf190fce7a
3 changed files with 43 additions and 5 deletions

View file

@ -75,7 +75,7 @@ class LogEntryManager(models.Manager):
if isinstance(pk, integer_types):
return self.filter(content_type=content_type, object_id=pk)
else:
return self.filter(content_type=content_type, object_pk=pk)
return self.filter(content_type=content_type, object_pk=smart_text(pk))
def get_for_objects(self, queryset):
"""
@ -90,10 +90,13 @@ class LogEntryManager(models.Manager):
return self.none()
content_type = ContentType.objects.get_for_model(queryset.model)
primary_keys = queryset.values_list(queryset.model._meta.pk.name, flat=True)
primary_keys = list(queryset.values_list(queryset.model._meta.pk.name, flat=True))
if isinstance(primary_keys[0], integer_types):
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_text(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()

View file

@ -1,3 +1,5 @@
import uuid
from django.db import models
from auditlog.models import AuditlogHistoryField
from auditlog.registry import auditlog
@ -32,6 +34,21 @@ class AltPrimaryKeyModel(models.Model):
history = AuditlogHistoryField(pk_indexable=False)
class UUIDPrimaryKeyModel(models.Model):
"""
A model with a UUID primary key.
"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
text = models.TextField(blank=True)
boolean = models.BooleanField(default=False)
integer = models.IntegerField(blank=True, null=True)
datetime = models.DateTimeField(auto_now=True)
history = AuditlogHistoryField(pk_indexable=False)
class ProxyModel(SimpleModel):
"""
A model that is a proxy for another model.
@ -121,6 +138,7 @@ class DateTimeFieldModel(models.Model):
auditlog.register(AltPrimaryKeyModel)
auditlog.register(UUIDPrimaryKeyModel)
auditlog.register(ProxyModel)
auditlog.register(RelatedModel)
auditlog.register(ManyRelatedModel)

View file

@ -9,9 +9,9 @@ from django.utils import timezone
from auditlog.middleware import AuditlogMiddleware
from auditlog.models import LogEntry
from auditlog.registry import auditlog
from auditlog_tests.models import SimpleModel, AltPrimaryKeyModel, ProxyModel, \
SimpleIncludeModel, SimpleExcludeModel, RelatedModel, ManyRelatedModel, AdditionalDataIncludedModel, \
DateTimeFieldModel
from auditlog_tests.models import SimpleModel, AltPrimaryKeyModel, UUIDPrimaryKeyModel, \
ProxyModel, SimpleIncludeModel, SimpleExcludeModel, RelatedModel, ManyRelatedModel, \
AdditionalDataIncludedModel, DateTimeFieldModel
class SimpleModelTest(TestCase):
@ -74,6 +74,23 @@ class AltPrimaryKeyModelTest(SimpleModelTest):
self.obj = AltPrimaryKeyModel.objects.create(key=str(datetime.datetime.now()), text='I am strange.')
class UUIDPrimaryKeyModelModelTest(SimpleModelTest):
def setUp(self):
self.obj = UUIDPrimaryKeyModel.objects.create(text='I am strange.')
def test_get_for_object(self):
self.obj.boolean = True
self.obj.save()
self.assertEqual(LogEntry.objects.get_for_object(self.obj).count(), 2)
def test_get_for_objects(self):
self.obj.boolean = True
self.obj.save()
self.assertEqual(LogEntry.objects.get_for_objects(UUIDPrimaryKeyModel.objects.all()).count(), 2)
class ProxyModelTest(SimpleModelTest):
def setUp(self):
self.obj = ProxyModel.objects.create(text='I am not what you think.')