Browse Source

feat(hadis): auto-populate title_narrator for hadith chains and non-hadith book authors

- Auto-populate title_narrator using 1st narrator known_as (or full_name) for hadith arguments
- Auto-populate title_narrator using reference book author known_as (or name) for non-hadith arguments
- Hook into Hadis.save, AdminHadisDetailSerializer create/update, and AdminHadisTransmitterViewSet relations
- Preserve manual entries when title_narrator is explicitly modified
master
Mohsen Taba 1 week ago
parent
commit
0f56ebb4aa
  1. 40
      apps/hadis/models/hadis.py
  2. 6
      apps/hadis/serializers/serializers_admin.py
  3. 14
      apps/hadis/views_admin.py

40
apps/hadis/models/hadis.py

@ -218,6 +218,42 @@ class Hadis(LowercaseSlugMixin, models.Model):
raise ValidationError(
_('Cannot assign hadith to a category that has subcategories. Only leaf categories can contain hadiths.')
)
def auto_populate_title_narrator(self):
"""
Auto-fills self.title_narrator if empty:
- For hadith (or items with transmitters): use the 'known_as' (fallback 'full_name') of the first narrator in the chain.
- For others (or non-hadith/quote/quran/fatwa/history): use the 'known_as' (fallback 'name') of the reference book's author.
"""
if self.title_narrator and isinstance(self.title_narrator, list):
has_val = any(
isinstance(item, dict) and item.get('text', '').strip()
for item in self.title_narrator
)
if has_val:
return False
# 1. Check first transmitter in chain
if self.pk:
first_trans_rel = self.transmitters.filter(transmitter__isnull=False).order_by('order', 'id').first()
if first_trans_rel and first_trans_rel.transmitter:
tr = first_trans_rel.transmitter
val = tr.known_as if (tr.known_as and isinstance(tr.known_as, list) and any(isinstance(x, dict) and x.get('text', '').strip() for x in tr.known_as)) else tr.full_name
if val and isinstance(val, list):
self.title_narrator = val
return True
# 2. Check book reference author
if self.pk:
ref = self.references.filter(book_reference__isnull=False, book_reference__author__isnull=False).first()
if ref and ref.book_reference and ref.book_reference.author:
author = ref.book_reference.author
val = author.known_as if (author.known_as and isinstance(author.known_as, list) and any(isinstance(x, dict) and x.get('text', '').strip() for x in author.known_as)) else author.name
if val and isinstance(val, list):
self.title_narrator = val
return True
return False
def save(self, *args, **kwargs):
self.clean()
@ -249,6 +285,10 @@ class Hadis(LowercaseSlugMixin, models.Model):
old_instance.translation != self.translation):
self.embedded_in = [] # Reset!
# Auto-fill title_narrator if empty
if not self.title_narrator or (isinstance(self.title_narrator, list) and not any(isinstance(item, dict) and item.get('text', '').strip() for item in self.title_narrator)):
self.auto_populate_title_narrator()
# Populate normalized_text for fast and accurate Arabic/Persian search
from utils.text_normalizer import build_search_blob
self.normalized_text = build_search_blob(

6
apps/hadis/serializers/serializers_admin.py

@ -718,6 +718,9 @@ class AdminHadisDetailSerializer(serializers.ModelSerializer):
pages=pages or "",
hadith_number=hadith_number or ""
)
if not hadis.title_narrator or (isinstance(hadis.title_narrator, list) and not any(isinstance(item, dict) and item.get('text', '').strip() for item in hadis.title_narrator)):
if hadis.auto_populate_title_narrator():
hadis.save(update_fields=['title_narrator', 'normalized_text'])
return hadis
def update(self, instance, validated_data):
@ -777,6 +780,9 @@ class AdminHadisDetailSerializer(serializers.ModelSerializer):
if hadith_number_provided:
ref.hadith_number = hadith_number or ""
ref.save()
if not hadis.title_narrator or (isinstance(hadis.title_narrator, list) and not any(isinstance(item, dict) and item.get('text', '').strip() for item in hadis.title_narrator)):
if hadis.auto_populate_title_narrator():
hadis.save(update_fields=['title_narrator', 'normalized_text'])
return hadis

14
apps/hadis/views_admin.py

@ -2340,6 +2340,20 @@ class AdminCategoryQuranVerseViewSet(ModelViewSet):
class AdminHadisTransmitterViewSet(ModelViewSet):
def perform_create(self, serializer):
instance = serializer.save()
hadis = instance.hadis
if hadis and (not hadis.title_narrator or (isinstance(hadis.title_narrator, list) and not any(isinstance(item, dict) and item.get('text', '').strip() for item in hadis.title_narrator))):
if hadis.auto_populate_title_narrator():
hadis.save(update_fields=['title_narrator', 'normalized_text'])
def perform_update(self, serializer):
instance = serializer.save()
hadis = instance.hadis
if hadis and (not hadis.title_narrator or (isinstance(hadis.title_narrator, list) and not any(isinstance(item, dict) and item.get('text', '').strip() for item in hadis.title_narrator))):
if hadis.auto_populate_title_narrator():
hadis.save(update_fields=['title_narrator', 'normalized_text'])
serializer_class = AdminHadisTransmitterSerializer
permission_classes = [IsAuthenticated, IsSuperAdmin]

Loading…
Cancel
Save