Browse Source

feat(hadis): return raw translations in sync api and invalidate cache on version update

- Return raw, unlocalized translation list in HadisSyncSerializer for Flutter offline multi-language support
- Enable hadis signals in HadisConfig.ready() to load cache invalidation listeners
- Add ContentRelease to TARGET_MODELS and implement invalidate_hadis_cache helper
- Trigger explicit cache invalidation in AdminContentReleaseViewSet upon version increment and CRUD
- Update HadisSyncView swagger documentation example
master
Mohsen Taba 2 weeks ago
parent
commit
73cf49958a
  1. 6
      apps/hadis/apps.py
  2. 7
      apps/hadis/docs.py
  3. 7
      apps/hadis/serializers/hadis.py
  4. 77
      apps/hadis/signals.py
  5. 19
      apps/hadis/views_admin.py

6
apps/hadis/apps.py

@ -4,6 +4,6 @@ from django.apps import AppConfig
class HadisConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.hadis'
# def ready(self):
# # Import the signals module when the app starts
# # import apps.hadis.signals
def ready(self):
# Import the signals module when the app starts
import apps.hadis.signals

7
apps/hadis/docs.py

@ -249,7 +249,12 @@ hadis_sync_swagger = swagger_auto_schema(
"title": "The Merit of Seeking Knowledge",
"title_narrator": "Jabir bin Abdullah",
"text": "اتَّقِ اللَّهَ حَيْثُمَا كُنْتَ، وَأَتْبِعِ السَّيِّئَةَ الْحَسَنَةَ تَمْحُهَا.",
"translation": "The best among you are those who have the best manners and character.",
"translation": [
{
"language_code": "en",
"text": "The best among you are those who have the best manners and character."
}
],
"detail": {
"address": [
"Sahih al-Bukhari",

7
apps/hadis/serializers/hadis.py

@ -90,9 +90,9 @@ class HadisSyncSerializer(serializers.ModelSerializer):
corrections = serializers.SerializerMethodField()
category_slug = serializers.CharField(source='category.slug', read_only=True)
interpretations = serializers.SerializerMethodField()
title =LocalizedField()
title = LocalizedField()
title_narrator = LocalizedField()
translation = LocalizedField()
translation = serializers.SerializerMethodField()
class Meta:
model = Hadis
@ -103,6 +103,9 @@ class HadisSyncSerializer(serializers.ModelSerializer):
'detail', 'narrators', 'explanations', 'corrections', 'interpretations'
]
def get_translation(self, obj):
return obj.translation or []
def get_detail(self, obj):
request = self.context.get('request')

77
apps/hadis/signals.py

@ -1,33 +1,44 @@
# hadith_app/signals.py
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.core.cache import cache
from .models import *
# 1. Define all models that affect the list
# If a Category title changes, the list must update.
# If a Status changes, the list must update.
TARGET_MODELS = [Hadis , HadisCategory , HadisCollection , HadisCorrection , HadisInCollection , HadisReference ,
HadisSect , HadisStatus , HadisTag , HadisTransmitter , Transmitters ,TransmitterOpinion , TransmitterReliability,
TransmitterOriginalText,ReferenceImage , BookReference , BookAttribute, BookAuthor ,BookReferenceImage,
NarratorLayer , OpinionStatus ]
@receiver(post_save)
@receiver(post_delete)
def clear_hadis_cache(sender, instance, **kwargs):
"""
Clears the API cache whenever a Hadith or related model is saved/deleted.
"""
if sender in TARGET_MODELS:
# This is the magic command from django-redis
# It finds ALL keys starting with the prefix and deletes them
# *:1: is the default django version prefix
try:
# Delete any key that contains our prefix "hadis_api"
# The pattern "*hadis_api*" ensures we catch all variations (headers, pages, etc)
cache.delete_pattern("*hadis_api*")
print(f"Cache cleared for {sender.__name__} update!")
except Exception as e:
# Fail silently or log error, don't crash the save transaction
print(f"Cache clear failed: {e}")
# hadith_app/signals.py
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.core.cache import cache
from .models import *
# 1. Define all models that affect the list
# If a Category title changes, the list must update.
# If a Status changes, the list must update.
TARGET_MODELS = [
Hadis, HadisCategory, HadisCollection, HadisCorrection, HadisInCollection, HadisReference,
HadisSect, HadisStatus, HadisTag, HadisTransmitter, Transmitters, TransmitterOpinion, TransmitterReliability,
TransmitterOriginalText, ReferenceImage, BookReference, BookAttribute, BookAuthor, BookReferenceImage,
NarratorLayer, OpinionStatus, ContentRelease
]
def invalidate_hadis_cache():
"""
Deletes all Redis cache keys matching '*hadis_api*'.
Falls back to cache.clear() if cache backend doesn't support delete_pattern.
"""
try:
if hasattr(cache, 'delete_pattern'):
deleted = cache.delete_pattern("*hadis_api*")
print(f"Cache cleared for hadis_api (deleted {deleted} keys)!")
else:
cache.clear()
print("Cache cleared for hadis_api (fallback clear)!")
except Exception as e:
# Fail silently or log error, don't crash the transaction
print(f"Cache clear failed: {e}")
@receiver(post_save)
@receiver(post_delete)
def clear_hadis_cache(sender, instance, **kwargs):
"""
Clears the API cache whenever a Hadith or related model is saved/deleted.
"""
if sender in TARGET_MODELS:
invalidate_hadis_cache()
print(f"Cache cleared for {sender.__name__} update!")

19
apps/hadis/views_admin.py

@ -968,6 +968,9 @@ class AdminContentReleaseViewSet(ModelViewSet):
is_active=True
)
from .signals import invalidate_hadis_cache
invalidate_hadis_cache()
return Response({
"status": "success",
"message": f"Version incremented to {version_name}",
@ -975,3 +978,19 @@ class AdminContentReleaseViewSet(ModelViewSet):
"next_suggested_version": compute_next_version(version_name)
})
def perform_create(self, serializer):
super().perform_create(serializer)
from .signals import invalidate_hadis_cache
invalidate_hadis_cache()
def perform_update(self, serializer):
super().perform_update(serializer)
from .signals import invalidate_hadis_cache
invalidate_hadis_cache()
def perform_destroy(self, instance):
super().perform_destroy(instance)
from .signals import invalidate_hadis_cache
invalidate_hadis_cache()
Loading…
Cancel
Save