Improving performance for history api

remotes/origin/issue/4795/notification_even_they_are_disabled
Alejandro Alonso 2016-05-11 15:02:02 +02:00
parent 576700afb6
commit 85acb93e22
3 changed files with 31 additions and 9 deletions

View File

@ -102,8 +102,8 @@ class HistoryViewSet(ReadOnlyListViewSet):
def retrieve(self, request, pk):
obj = self.get_object()
self.check_permissions(request, "retrieve", obj)
qs = services.get_history_queryset_by_model_instance(obj)
qs = services.prefetch_owners_in_history_queryset(qs)
return self.response_for_queryset(qs)

View File

@ -78,6 +78,8 @@ class HistoryEntry(models.Model):
is_snapshot = models.BooleanField(default=False)
_importing = None
_owner = None
_prefetched_owner = False
@cached_property
def is_change(self):
@ -91,14 +93,23 @@ class HistoryEntry(models.Model):
def is_delete(self):
return self.type == HistoryType.delete
@cached_property
@property
def owner(self):
pk = self.user["pk"]
model = get_user_model()
try:
return model.objects.get(pk=pk)
except model.DoesNotExist:
return None
if not self._prefetched_owner:
pk = self.user["pk"]
model = get_user_model()
try:
owner = model.objects.get(pk=pk)
except model.DoesNotExist:
owner = None
self.prefetch_owner(owner)
return self._owner
def prefetch_owner(self, owner):
self._owner = owner
self._prefetched_owner = True
@cached_property
def values_diff(self):

View File

@ -33,6 +33,7 @@ from functools import wraps
from functools import lru_cache
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.core.paginator import Paginator, InvalidPage
from django.apps import apps
@ -331,7 +332,7 @@ def take_snapshot(obj:object, *, comment:str="", user=None, delete:bool=False):
"is_hidden": is_hidden,
"is_snapshot": need_real_snapshot,
}
return entry_model.objects.create(**kwargs)
@ -352,6 +353,16 @@ def get_history_queryset_by_model_instance(obj:object, types=(HistoryType.change
return qs.order_by("created_at")
def prefetch_owners_in_history_queryset(qs):
user_ids = [u["pk"] for u in qs.values_list("user", flat=True)]
users = get_user_model().objects.filter(id__in=user_ids)
users_by_id = {u.id: u for u in users}
for history_entry in qs:
history_entry.prefetch_owner(users_by_id.get(history_entry.user["pk"], None))
return qs
# Freeze implementatitions
from .freeze_impl import project_freezer
from .freeze_impl import milestone_freezer