Browse Source

perf(hadis): enable optional pagination on archive viewsets and eliminate N+1 queries in corrections and categories

master
Mohsen Taba 6 days ago
parent
commit
cf431ffb9d
  1. 23
      apps/hadis/serializers/serializers_admin.py
  2. 76
      apps/hadis/views_admin.py

23
apps/hadis/serializers/serializers_admin.py

@ -186,6 +186,13 @@ class AdminHadisCategorySerializer(serializers.ModelSerializer):
return [] return []
view = self.context.get("view")
request = self.context.get("request")
if getattr(view, "action", None) == "list":
include_ancestors = request.query_params.get("include_ancestors") if request else None
if str(include_ancestors).lower() not in ("true", "1"):
return []
ancestors_qs = obj.get_ancestors(include_self=True).select_related('sect') ancestors_qs = obj.get_ancestors(include_self=True).select_related('sect')
return [ return [
@ -576,7 +583,7 @@ class AdminHadisReferenceSerializer(serializers.ModelSerializer):
author = obj.book_reference.author author = obj.book_reference.author
first_ed = obj.book_reference.editions.first() if hasattr(obj.book_reference, "editions") else None
first_ed = next(iter(obj.book_reference.editions.all()), None) if hasattr(obj.book_reference, "editions") else None
pub = getattr(obj.book_reference, "publisher", None) pub = getattr(obj.book_reference, "publisher", None)
@ -700,7 +707,7 @@ class AdminHadisReferenceSerializer(serializers.ModelSerializer):
} }
for img in obj.images.all().order_by("priority", "id")
for img in sorted(obj.images.all(), key=lambda x: (x.priority or 0, x.id or 0))
] ]
@ -1190,7 +1197,7 @@ class AdminHadisDetailSerializer(serializers.ModelSerializer):
author = ref.book_reference.author author = ref.book_reference.author
first_ed = ref.book_reference.editions.first() if hasattr(ref.book_reference, "editions") else None
first_ed = next(iter(ref.book_reference.editions.all()), None) if hasattr(ref.book_reference, "editions") else None
pub = getattr(ref.book_reference, "publisher", None) pub = getattr(ref.book_reference, "publisher", None)
@ -1802,7 +1809,7 @@ class AdminCorrectionReferenceSerializer(serializers.ModelSerializer):
author = obj.book_reference.author author = obj.book_reference.author
first_ed = obj.book_reference.editions.first() if hasattr(obj.book_reference, "editions") else None
first_ed = next(iter(obj.book_reference.editions.all()), None) if hasattr(obj.book_reference, "editions") else None
pub = getattr(obj.book_reference, "publisher", None) pub = getattr(obj.book_reference, "publisher", None)
@ -2232,8 +2239,6 @@ class AdminHadisCorrectionSerializer(serializers.ModelSerializer):
] ]
ret["references"] = AdminCorrectionReferenceSerializer(instance.references.all(), many=True, context=self.context).data
return ret return ret
@ -2364,7 +2369,7 @@ class AdminInterpretationReferenceSerializer(serializers.ModelSerializer):
author = obj.book_reference.author author = obj.book_reference.author
first_ed = obj.book_reference.editions.first() if hasattr(obj.book_reference, "editions") else None
first_ed = next(iter(obj.book_reference.editions.all()), None) if hasattr(obj.book_reference, "editions") else None
pub = getattr(obj.book_reference, "publisher", None) pub = getattr(obj.book_reference, "publisher", None)
@ -2670,7 +2675,7 @@ class AdminOriginalTextReferenceSerializer(serializers.ModelSerializer):
author = obj.book_reference.author author = obj.book_reference.author
first_ed = obj.book_reference.editions.first() if hasattr(obj.book_reference, "editions") else None
first_ed = next(iter(obj.book_reference.editions.all()), None) if hasattr(obj.book_reference, "editions") else None
pub = getattr(obj.book_reference, "publisher", None) pub = getattr(obj.book_reference, "publisher", None)
@ -3094,8 +3099,6 @@ class AdminHadisInterpretationSerializer(serializers.ModelSerializer):
] ]
ret["references"] = AdminInterpretationReferenceSerializer(instance.references.all(), many=True, context=self.context).data
return ret return ret

76
apps/hadis/views_admin.py

@ -282,7 +282,7 @@ class DovodiHadisSectViewSet(ModelViewSet):
authentication_classes = [TokenAuthentication] authentication_classes = [TokenAuthentication]
pagination_class = None
pagination_class = OptionalPagination
parser_classes = (JSONParser, MultiPartParser, FormParser) parser_classes = (JSONParser, MultiPartParser, FormParser)
@ -320,7 +320,7 @@ class DovodiHadisCategoryViewSet(ModelViewSet):
authentication_classes = [TokenAuthentication] authentication_classes = [TokenAuthentication]
pagination_class = None
pagination_class = OptionalPagination
parser_classes = (JSONParser, MultiPartParser, FormParser) parser_classes = (JSONParser, MultiPartParser, FormParser)
@ -484,7 +484,7 @@ class AdminHadisTagViewSet(ModelViewSet):
authentication_classes = [TokenAuthentication] authentication_classes = [TokenAuthentication]
pagination_class = None
pagination_class = OptionalPagination
parser_classes = (JSONParser, MultiPartParser, FormParser) parser_classes = (JSONParser, MultiPartParser, FormParser)
@ -514,7 +514,7 @@ class AdminHadisCollectionViewSet(ModelViewSet):
authentication_classes = [TokenAuthentication] authentication_classes = [TokenAuthentication]
pagination_class = None
pagination_class = OptionalPagination
parser_classes = (MultiPartParser, FormParser, JSONParser) parser_classes = (MultiPartParser, FormParser, JSONParser)
@ -1366,7 +1366,7 @@ class AdminHadisCorrectionViewSet(ModelViewSet):
def get_queryset(self): def get_queryset(self):
from django.db.models import Count, OuterRef, Subquery, IntegerField
from django.db.models import Count, OuterRef, Subquery, IntegerField, Prefetch
from django.db.models.functions import Coalesce from django.db.models.functions import Coalesce
@ -1386,10 +1386,35 @@ class AdminHadisCorrectionViewSet(ModelViewSet):
queryset = HadisCorrection.objects.all().select_related("hadis").prefetch_related("references", "references__images").annotate(
annotated_bookmark_count=Coalesce(Subquery(bookmarks_subquery, output_field=IntegerField()), 0)
references_prefetch = Prefetch(
"references",
queryset=CorrectionReference.objects.select_related(
"book_reference__author", "edition", "book_volume"
).defer(
"book_reference__description",
"book_reference__normalized_text",
"book_reference__author__scholarity",
"book_reference__author__features",
).prefetch_related("images", "book_reference__editions").order_by("id"),
)
queryset = (
HadisCorrection.objects.all()
.defer(
"normalized_text",
"embedded_in",
"hadis__text",
"hadis__translation",
"hadis__explanation",
"hadis__description",
"hadis__normalized_text",
"hadis__embedded_in",
)
.select_related("hadis")
.prefetch_related(references_prefetch)
.annotate(
annotated_bookmark_count=Coalesce(Subquery(bookmarks_subquery, output_field=IntegerField()), 0)
)
) )
hadis_id = self.request.query_params.get("hadis_id") or self.request.query_params.get("hadis") hadis_id = self.request.query_params.get("hadis_id") or self.request.query_params.get("hadis")
@ -1482,7 +1507,7 @@ class AdminCorrectionReferenceViewSet(ModelViewSet):
"book_reference__author", "edition", "book_volume" "book_reference__author", "edition", "book_volume"
).prefetch_related("images")
).prefetch_related("images", "book_reference__editions")
correction_id = self.request.query_params.get("correction_id") correction_id = self.request.query_params.get("correction_id")
@ -1516,7 +1541,7 @@ class AdminHadisReferenceViewSet(ModelViewSet):
"book_reference__author", "edition", "book_volume" "book_reference__author", "edition", "book_volume"
).prefetch_related("images")
).prefetch_related("images", "book_reference__editions")
hadis_id = self.request.query_params.get("hadis_id") hadis_id = self.request.query_params.get("hadis_id")
@ -1563,7 +1588,7 @@ class AdminInterpretationReferenceViewSet(ModelViewSet):
"book_reference__author", "edition", "book_volume" "book_reference__author", "edition", "book_volume"
).prefetch_related("images")
).prefetch_related("images", "book_reference__editions")
interpretation_id = self.request.query_params.get("interpretation_id") or self.request.query_params.get("interpretation") interpretation_id = self.request.query_params.get("interpretation_id") or self.request.query_params.get("interpretation")
@ -1611,7 +1636,7 @@ class AdminOriginalTextReferenceViewSet(ModelViewSet):
"book_reference__author", "edition", "book_volume" "book_reference__author", "edition", "book_volume"
).prefetch_related("images")
).prefetch_related("images", "book_reference__editions")
original_text_id = self.request.query_params.get("original_text_id") or self.request.query_params.get("original_text") original_text_id = self.request.query_params.get("original_text_id") or self.request.query_params.get("original_text")
@ -1641,7 +1666,26 @@ class AdminHadisInterpretationViewSet(ModelViewSet):
def get_queryset(self): def get_queryset(self):
queryset = HadisInterpretation.objects.all().select_related("category").prefetch_related("references", "references__images")
from django.db.models import Prefetch
references_prefetch = Prefetch(
"references",
queryset=InterpretationReference.objects.select_related(
"book_reference__author", "edition", "book_volume"
).defer(
"book_reference__description",
"book_reference__normalized_text",
"book_reference__author__scholarity",
"book_reference__author__features",
).prefetch_related("images", "book_reference__editions").order_by("id"),
)
queryset = (
HadisInterpretation.objects.all()
.defer("normalized_text", "category__description")
.select_related("category")
.prefetch_related(references_prefetch)
)
category_id = self.request.query_params.get("category_id") or self.request.query_params.get("category") category_id = self.request.query_params.get("category_id") or self.request.query_params.get("category")
@ -1761,7 +1805,7 @@ class DovodiBookSubjectAreaViewSet(ModelViewSet):
authentication_classes = [TokenAuthentication] authentication_classes = [TokenAuthentication]
pagination_class = None
pagination_class = OptionalPagination
parser_classes = (JSONParser, MultiPartParser, FormParser) parser_classes = (JSONParser, MultiPartParser, FormParser)
@ -1791,7 +1835,7 @@ class DovodiBookTypeViewSet(ModelViewSet):
authentication_classes = [TokenAuthentication] authentication_classes = [TokenAuthentication]
pagination_class = None
pagination_class = OptionalPagination
parser_classes = (JSONParser, MultiPartParser, FormParser) parser_classes = (JSONParser, MultiPartParser, FormParser)
@ -2624,7 +2668,7 @@ class AdminBookTagViewSet(ModelViewSet):
serializer_class = AdminBookTagSerializer serializer_class = AdminBookTagSerializer
pagination_class = None
pagination_class = OptionalPagination
parser_classes = (JSONParser, MultiPartParser, FormParser) parser_classes = (JSONParser, MultiPartParser, FormParser)

Loading…
Cancel
Save