diff --git a/taiga/projects/history/api.py b/taiga/projects/history/api.py index 9d958d0e..d10194ce 100644 --- a/taiga/projects/history/api.py +++ b/taiga/projects/history/api.py @@ -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) diff --git a/taiga/projects/history/models.py b/taiga/projects/history/models.py index d440900c..e947c6fe 100644 --- a/taiga/projects/history/models.py +++ b/taiga/projects/history/models.py @@ -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): diff --git a/taiga/projects/history/services.py b/taiga/projects/history/services.py index 399b486f..22839ec8 100644 --- a/taiga/projects/history/services.py +++ b/taiga/projects/history/services.py @@ -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