From 283441bbc4ce83f63dab22f46e935c32c98d2d6c Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Sun, 26 Apr 2026 11:15:52 +0330 Subject: [PATCH] professor details caching enhancement professors course list is cache cleared now signal added to clear cache after any change happend in the professor object --- apps/course/signals.py | 30 ++++++++++++++++++++++++++---- apps/course/views/professor.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/apps/course/signals.py b/apps/course/signals.py index 1048c84..4074622 100644 --- a/apps/course/signals.py +++ b/apps/course/signals.py @@ -1,9 +1,13 @@ -from django.db.models.signals import post_save -from django.dispatch import receiver - from apps.course.models import Course from apps.chat.models import RoomMessage +from django.db.models.signals import post_save, post_delete +from django.dispatch import receiver +from django.core.cache import cache +from django.contrib.auth import get_user_model + +UserModel = get_user_model() + @receiver(post_save, sender=Course) def handle_room_message_for_course(sender, instance, created, **kwargs): @@ -31,4 +35,22 @@ def handle_room_message_for_course(sender, instance, created, **kwargs): def ensure_professor_role(sender, instance, **kwargs): professor = getattr(instance, 'professor', None) if professor: - professor.ensure_professor_profile() \ No newline at end of file + professor.ensure_professor_profile() + +@receiver([post_save, post_delete], sender=Course) +def invalidate_professor_course_cache(sender, instance, **kwargs): + """ + Clears the cached professor detail page AND their course list + whenever a course assigned to them is created, updated, or deleted. + """ + if instance.professor: + detail_cache_key = f"professor_detail_{instance.professor.slug}" + + cache.delete(detail_cache_key) + +# Optional: If you update a Professor's profile in the admin directly +@receiver([post_save, post_delete], sender=UserModel) +def invalidate_professor_profile_cache(sender, instance, **kwargs): + if instance.user_type == UserModel.UserType.PROFESSOR: + cache_key = f"professor_detail_{instance.slug}" + cache.delete(cache_key) \ No newline at end of file diff --git a/apps/course/views/professor.py b/apps/course/views/professor.py index 287b58c..2cdf251 100644 --- a/apps/course/views/professor.py +++ b/apps/course/views/professor.py @@ -15,6 +15,10 @@ from apps.course.serializers import ( ProfessorListSerializer, ) from utils.pagination import StandardResultsSetPagination +from django.utils.decorators import method_decorator +from django.views.decorators.cache import never_cache +from django.core.cache import cache +from rest_framework.response import Response UserModel = get_user_model() @@ -108,6 +112,25 @@ class ProfessorDetailAPIView(RetrieveAPIView): def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) + def retrieve(self, request, *args, **kwargs): + slug = self.kwargs.get('slug') + cache_key = f"professor_detail_{slug}" + + # Try to get the data from Redis/Cache + cached_data = cache.get(cache_key) + if cached_data: + return Response(cached_data) + + # If not in cache, let DRF do the heavy lifting (DB queries, serialization) + response = super().retrieve(request, *args, **kwargs) + + # Store the serialized data in the cache for 24 hours + cache.set(cache_key, response.data, timeout=60 * 60 * 24) + + return response + + + def get_queryset(self): return UserModel.objects.filter(user_type=UserModel.UserType.PROFESSOR).annotate( course_count=Count('courses', distinct=True), @@ -122,6 +145,11 @@ class ProfessorCourseListAPIView(ListAPIView): search_fields = ['title', 'category__name'] pagination_class = StandardResultsSetPagination + @method_decorator(never_cache) + def dispatch(self, request, *args, **kwargs): + return super().dispatch(request, *args, **kwargs) + + @swagger_auto_schema( operation_description='دریافت فهرست دوره‌های فعال یک استاد مشخص‌شده با اسلاگ.', tags=['Imam-Javad - Course'],