Browse Source

Sync hadis fixed n+1 and indexing

master
Mohsen Taba 5 months ago
parent
commit
21682622ff
  1. 18
      apps/hadis/migrations/0064_hadis_hadis_hadis_status_5e0de5_idx.py
  2. 4
      apps/hadis/models/hadis.py
  3. 60
      apps/hadis/serializers/hadis.py
  4. 31
      apps/hadis/views/hadis.py

18
apps/hadis/migrations/0064_hadis_hadis_hadis_status_5e0de5_idx.py

@ -0,0 +1,18 @@
# Generated by Django 4.2.27 on 2025-12-22 13:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0063_alter_transmitteroriginaltext_slug"),
]
operations = [
migrations.AddIndex(
model_name="hadis",
index=models.Index(
fields=["status", "id"], name="hadis_hadis_status_5e0de5_idx"
),
),
]

4
apps/hadis/models/hadis.py

@ -293,6 +293,10 @@ class Hadis(models.Model):
super().save(*args, **kwargs)
class Meta:
indexes = [
# Optimizes: Hadis.objects.filter(status=True).order_by('id')
models.Index(fields=['status', 'id']),
]
verbose_name = _('hadis')
verbose_name_plural = _('hadises')
ordering = ('category', 'number')

60
apps/hadis/serializers/hadis.py

@ -54,7 +54,6 @@ class HadisSyncSerializer(serializers.ModelSerializer):
]
def get_detail(self, obj):
"""Detail group: address, status, share, links, tags, references, reference_images"""
request = self.context.get('request')
# status
@ -62,24 +61,33 @@ class HadisSyncSerializer(serializers.ModelSerializer):
if obj.hadis_status:
status_block = {
'id': obj.hadis_status.id,
'title': get_localized_text(obj.hadis_status.title,request),
'color': obj.hadis_status.color
'title': get_localized_text(obj.hadis_status.title, request),
'color': obj.hadis_status.color,
}
# tags
tags_block = [{'id': tag.id, 'title': get_localized_text(tag.title,request)} for tag in obj.tags.all()]
# tags (already prefetched)
tags_block = [
{'id': tag.id, 'title': get_localized_text(tag.title, request)}
for tag in obj.tags.all()
]
# references and reference images
# references and reference images (already prefetched)
references_block = []
reference_images_block = []
for reference in obj.references.select_related('book_reference').prefetch_related('book_reference__authors', 'images'):
for reference in obj.references.all():
book = reference.book_reference
authors = book.authors.all() if book else []
references_block.append({
'id': reference.id,
'title': get_localized_text(book.title,request) if book else None,
'authors': [{'id': a.id, 'name': get_localized_text(a.name,request)} for a in book.authors.all()] if book else [],
'title': get_localized_text(book.title, request) if book else None,
'authors': [
{'id': a.id, 'name': get_localized_text(a.name, request)}
for a in authors
],
'description': book.description if book else None,
})
for img in reference.images.all().order_by('priority'):
thumb_url = None
if img.thumbnail:
@ -91,9 +99,9 @@ class HadisSyncSerializer(serializers.ModelSerializer):
})
return {
'address': get_localized_text(obj.address,request),
'address': get_localized_text(obj.address, request),
'hadis_status': status_block,
'status_text':get_localized_text(obj.hadis_status_text,request) ,
'status_text': get_localized_text(obj.hadis_status_text, request),
'share_link': obj.share_link,
'links': obj.links,
'tags': tags_block,
@ -101,17 +109,20 @@ class HadisSyncSerializer(serializers.ModelSerializer):
'reference_images': reference_images_block,
}
def get_narrators(self, obj):
"""Narrators group: description + transmitters"""
request = self.context.get('request')
transmitters_data = []
for transmitter_rel in obj.transmitters.select_related('transmitter', 'narrator_layer').order_by('order'):
for transmitter_rel in obj.transmitters.all():
t = transmitter_rel.transmitter
layer = transmitter_rel.narrator_layer
transmitters_data.append({
'id': t.id,
'name': get_localized_text(t.full_name,request),
'name': get_localized_text(t.full_name, request),
'reliability': t.reliability,
'layer_level': transmitter_rel.narrator_layer.number if transmitter_rel.narrator_layer else None,
'layer_name': get_localized_text(transmitter_rel.narrator_layer.name,request) if transmitter_rel.narrator_layer else None,
'layer_level': layer.number if layer else None,
'layer_name': get_localized_text(layer.name, request) if layer else None,
'is_gap': transmitter_rel.is_gap,
'birth_year_hijri': t.birth_year_hijri,
'death_year_hijri': t.death_year_hijri,
@ -119,23 +130,24 @@ class HadisSyncSerializer(serializers.ModelSerializer):
})
return {
'description': get_localized_text(obj.description,request),
'transmitters': transmitters_data
'description': get_localized_text(obj.description, request),
'transmitters': transmitters_data,
}
def get_explanations(self, obj):
"""Explanations group"""
return get_localized_text(obj.explanation,request)
request = self.context.get('request')
return get_localized_text(obj.explanation, request)
def get_corrections(self, obj):
"""Corrections group"""
request = self.context.get('request')
corrections_data = []
for correction in obj.hadiscorrection_set.all():
corrections_data.append({
'id': correction.id,
'title': get_localized_text(correction.title,request),
'description': get_localized_text(correction.description,request),
'translation': get_localized_text(correction.translation,request),
'title': get_localized_text(correction.title, request),
'description': get_localized_text(correction.description, request),
'translation': get_localized_text(correction.translation, request),
'share_link': correction.share_link,
})
return corrections_data

31
apps/hadis/views/hadis.py

@ -6,7 +6,7 @@ from django.db.models import Count
from django.db.models import Prefetch
from ..serializers.category import get_localized_text
from ..models import HadisCategory, Hadis, HadisCollection,HadisTransmitter , HadisCorrection
from ..models import HadisCategory, Hadis, HadisCollection,HadisTransmitter , HadisCorrection ,HadisReference
from ..serializers import HadisListSerializer, HadisBasicSerializer, HadisDetailSerializer, HadisCollectionListSerializer, HadisSyncSerializer,HadisCorrectionSerializer,HadisTransmitterListSerializer
from ..docs import hadis_list_swagger, hadis_detail_swagger, hadis_collections_swagger, hadis_sync_swagger, hadis_transmitters_swagger, hadis_corrections_swagger, hadis_basic_swagger, hadis_main_list_swagger
@ -32,15 +32,26 @@ class HadisSyncView(ListAPIView):
pagination_class = NoPagination
def get_queryset(self):
return Hadis.objects.filter(status=True).select_related(
'category', 'hadis_status'
).prefetch_related(
'tags',
'transmitters__transmitter',
'references__images',
'references__book_reference',
'hadiscorrection_set'
).order_by('id')
return (
Hadis.objects
.filter(status=True)
.select_related('category', 'hadis_status')
.prefetch_related(
'tags',
Prefetch(
'transmitters',
queryset=HadisTransmitter.objects.select_related('transmitter', 'narrator_layer').order_by('order')
),
Prefetch(
'references',
queryset=HadisReference.objects
.select_related('book_reference')
.prefetch_related('book_reference__authors', 'images')
),
'hadiscorrection_set',
)
.order_by('id')
)
@hadis_sync_swagger
def get(self, request, *args, **kwargs):

Loading…
Cancel
Save