Browse Source

added authentication method and bookmark settings to hadis and reference details.

master
Mohsen Taba 4 months ago
parent
commit
0f609b7d7a
  1. 29
      apps/hadis/serializers/hadis.py
  2. 6
      apps/hadis/serializers/reference.py
  3. 6
      apps/hadis/urls.py
  4. 41
      apps/hadis/views/hadis.py
  5. 4
      apps/hadis/views/reference.py
  6. 1
      apps/video/serializers.py
  7. 4
      apps/video/urls.py
  8. 114
      apps/video/views.py

29
apps/hadis/serializers/hadis.py

@ -5,6 +5,7 @@ from urllib3 import request
from .category import LocalizedField
from .category import get_localized_text
from .category import get_localized_text
from apps.bookmark.serializers.bookmark import BookmarkStatusSerializer
from ..models import (
Hadis, HadisStatus, HadisTag, HadisTransmitter,
@ -156,6 +157,7 @@ class HadisListSerializer(serializers.ModelSerializer):
"""Serializer for Hadis list"""
category = serializers.SerializerMethodField()
status = serializers.SerializerMethodField()
bookmark = serializers.SerializerMethodField()
translation = LocalizedField()
title = LocalizedField()
title_narrator = LocalizedField()
@ -163,7 +165,7 @@ class HadisListSerializer(serializers.ModelSerializer):
class Meta:
model = Hadis
fields = ['id', 'number', 'slug', 'title', 'title_narrator', 'text',
'translation', 'category', 'status', 'share_link']
'translation', 'category', 'status', 'bookmark', 'share_link']
def get_category(self, obj):
"""Get category id and title"""
@ -203,6 +205,17 @@ class HadisListSerializer(serializers.ModelSerializer):
'color': obj.hadis_status.color
}
def get_bookmark(self, obj):
"""Get bookmark information for this playlist."""
request = self.context.get('request')
user = request.user if request else None
book_mark = BookmarkStatusSerializer.get_bookmark_info(
obj=obj,
user=user,
service='hadith'
)
return book_mark.get('is_bookmarked', False)
class HadisStatusSerializer(serializers.ModelSerializer):
"""Serializer for HadisStatus"""
title = LocalizedField()
@ -573,6 +586,7 @@ class HadisBasicSerializer(serializers.ModelSerializer):
"""Basic serializer for Hadis with minimal information"""
translation = LocalizedField()
category = serializers.SerializerMethodField()
bookmark= serializers.SerializerMethodField()
title = LocalizedField()
title_narrator = LocalizedField()
@ -581,7 +595,7 @@ class HadisBasicSerializer(serializers.ModelSerializer):
class Meta:
model = Hadis
fields = [
'id', 'slug', 'title', 'title_narrator', 'text',
'id', 'slug', 'title','bookmark', 'title_narrator', 'text',
'translation', 'share_link','explanation','category'
]
@ -599,6 +613,17 @@ class HadisBasicSerializer(serializers.ModelSerializer):
'sect_type':obj.category.sect.sect_type
}
return None
def get_bookmark(self, obj):
"""Get bookmark information for this playlist."""
request = self.context.get('request')
user = request.user if request else None
book_mark = BookmarkStatusSerializer.get_bookmark_info(
obj=obj,
user=user,
service='hadith'
)
return book_mark.get('is_bookmarked', False)
class HadisShortSerializer(serializers.ModelSerializer):
"""Basic serializer for Hadis with minimal information"""

6
apps/hadis/serializers/reference.py

@ -77,6 +77,7 @@ class BookAttributeSerializer(serializers.ModelSerializer):
model = BookAttribute
fields = ['id', 'title', 'value','book_reference']
from apps.hadis.serializers import HadisListSerializer
class BookDetailSerializer(serializers.ModelSerializer):
attribute = BookAttributeSerializer(
@ -100,7 +101,6 @@ class BookDetailSerializer(serializers.ModelSerializer):
# read_only=True,
# source='hadis_references__hadis'
# )
hadis = serializers.SerializerMethodField()
title = LocalizedField()
language = LocalizedField()
@ -114,7 +114,7 @@ class BookDetailSerializer(serializers.ModelSerializer):
def get_hadis(self,obj):
references = obj.hadis_references.all()
hadis_list = [ref.hadis for ref in references if ref.hadis]
return HadisBasicSerializer(hadis_list,many=True).data
return HadisListSerializer(hadis_list,many=True, context=self.context).data
@ -166,4 +166,4 @@ class BookReferenceSyncSerializer(serializers.ModelSerializer):
def get_hadises(self,obj):
references = obj.hadis_references.all()
hadis_list = [ref.hadis for ref in references if ref.hadis]
return HadisShortSerializer(hadis_list,many=True).data
return HadisShortSerializer(hadis_list,many=True, context=self.context).data

6
apps/hadis/urls.py

@ -32,7 +32,7 @@ urlpatterns = [
path('categories/', cached_view(CategoriesView.as_view()), name='categories'), # ← Least specific LAST
# Hadis paths
path('category/<str:category_slug>/', cached_view(HadisListView.as_view()), name='hadis-list'),
path('category/<str:category_slug>/', HadisListView.as_view(), name='hadis-list'),
path('arguments/', cached_view(HadisMainListView.as_view()), name='hadis-main-list'),
path('arguments/filters/', cached_view(HadisFiltersView.as_view()), name='hadis-filters'),
@ -44,11 +44,11 @@ urlpatterns = [
path('narrators/', cached_view(TransmitterView.as_view()), name='narrators'),
# Reference paths
path('references/<str:reference_slug>', cached_view(BookDetailView.as_view()), name='reference-detail'),
path('references/<str:reference_slug>', BookDetailView.as_view(), name='reference-detail'),
path('references/', cached_view(BookReferencesView.as_view()), name='references'),
# Hadis detail paths (with slug, more specific)
path('<str:hadis_slug>/detail/', cached_view(HadisDetailView.as_view()), name='hadis-detail'),
path('<str:hadis_slug>/detail/', HadisDetailView.as_view(), name='hadis-detail'),
path('<str:hadis_slug>/transmitters/', cached_view(HadisTransmittersView.as_view()), name='hadis-transmitters'),
path('<str:hadis_slug>/corrections/', cached_view(HadisCorrectionsView.as_view()), name='hadis-corrections'),
path('<str:hadis_slug>/', cached_view(HadisBasicView.as_view()), name='hadis-basic'), # ← Least specific LAST

41
apps/hadis/views/hadis.py

@ -1,3 +1,4 @@
from rest_framework.authentication import TokenAuthentication
from rest_framework.generics import ListAPIView, RetrieveAPIView
from django.shortcuts import get_object_or_404
from utils.pagination import NoPagination, StandardResultsSetPagination
@ -88,6 +89,7 @@ class HadisListView(ListAPIView):
"""
serializer_class = HadisListSerializer
pagination_class = StandardResultsSetPagination
authentication_classes = [TokenAuthentication]
@hadis_list_swagger
def get(self, request, *args, **kwargs):
@ -135,6 +137,25 @@ class HadisListView(ListAPIView):
layer_count=Count('transmitters__narrator_layer', distinct=True)
).select_related('category')
def get_serializer_context(self):
"""Add user bookmarks to serializer context to avoid caching issues"""
context = super().get_serializer_context()
# Add user's bookmarked hadis IDs to context
user = self.request.user
if user.is_authenticated:
from apps.bookmark.models.bookmark import Bookmark
user_bookmarks = Bookmark.objects.filter(
user=user,
service=Bookmark.ServiceChoices.HADITH,
status=True
).values_list('content_id', flat=True)
context['user_bookmarked_hadis_ids'] = set(user_bookmarks)
else:
context['user_bookmarked_hadis_ids'] = set()
return context
@ -289,6 +310,7 @@ class HadisBasicView(RetrieveAPIView):
serializer_class = HadisBasicSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'hadis_slug'
authentication_classes = [TokenAuthentication]
@hadis_basic_swagger
def get(self, request, *args, **kwargs):
@ -297,6 +319,25 @@ class HadisBasicView(RetrieveAPIView):
def get_queryset(self):
return Hadis.objects.filter(status=True)
def get_serializer_context(self):
"""Add user bookmarks to serializer context to avoid caching issues"""
context = super().get_serializer_context()
# Add user's bookmarked hadis IDs to context
user = self.request.user
if user.is_authenticated:
from apps.bookmark.models.bookmark import Bookmark
user_bookmarks = Bookmark.objects.filter(
user=user,
service=Bookmark.ServiceChoices.HADITH,
status=True
).values_list('content_id', flat=True)
context['user_bookmarked_hadis_ids'] = set(user_bookmarks)
else:
context['user_bookmarked_hadis_ids'] = set()
return context
class HadisDetailView(RetrieveAPIView):
"""

4
apps/hadis/views/reference.py

@ -1,3 +1,5 @@
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import ListAPIView, RetrieveAPIView,ListCreateAPIView
from rest_framework.response import Response
from django.db.models import Q
@ -59,6 +61,8 @@ class BookDetailView(RetrieveAPIView):
serializer_class = BookDetailSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'reference_slug'
permission_classes = (IsAuthenticated,)
authentication_classes = [TokenAuthentication]
@book_detail_swagger
def get(self, request, *args, **kwargs):

1
apps/video/serializers.py

@ -95,6 +95,7 @@ class VideoPlaylistDetailSerializer(serializers.ModelSerializer):
"""Get bookmark information for this playlist."""
request = self.context.get('request')
user = request.user if request else None
print(user.id)
book_mark = BookmarkStatusSerializer.get_bookmark_info(
obj=obj,
user=user,

4
apps/video/urls.py

@ -12,6 +12,6 @@ urlpatterns = [
re_path(r'playlists/(?P<slug>[\w-]+)/$', VideoPlaylistDetailAPIView.as_view(), name='playlist-detail'),
# Keep old video endpoints for backward compatibility if needed
path('list/', VideoPlaylistListAPIView.as_view(), name='video-list'),
re_path(r'detail/(?P<slug>[\w-]+)/$', VideoPlaylistDetailAPIView.as_view(), name='video-detail'),
path('list/', VideoListAPIView.as_view(), name='video-list'),
re_path(r'detail/(?P<slug>[\w-]+)/$', VideoDetailAPIView.as_view(), name='video-detail'),
]

114
apps/video/views.py

@ -216,6 +216,108 @@ class VideoPlaylistListAPIView(generics.ListAPIView):
return queryset
class VideoListAPIView(generics.ListAPIView):
"""
API view to list all video playlists, with optional filtering by category or collection
"""
serializer_class = VideoListSerializer
permission_classes = (IsAuthenticated,)
authentication_classes = [TokenAuthentication]
pagination_class = StandardResultsSetPagination
@swagger_auto_schema(
operation_description="Get a list of videos with optional filtering",
tags=["Dobodbi - Video"],
manual_parameters=[
openapi.Parameter(
name='category',
in_=openapi.IN_QUERY,
description='Filter playlists by category slug',
type=openapi.TYPE_STRING,
required=False
),
openapi.Parameter(
name='collection',
in_=openapi.IN_QUERY,
description='Filter playlists by collection slug',
type=openapi.TYPE_STRING,
required=False
),
openapi.Parameter(
name='is_bookmark',
in_=openapi.IN_QUERY,
description='Filter playlists that are bookmarked by the user (true/false)',
type=openapi.TYPE_BOOLEAN,
required=False
),
openapi.Parameter(
name='search',
in_=openapi.IN_QUERY,
description='Search playlists by title',
type=openapi.TYPE_STRING,
required=False
)
],
responses={
200: openapi.Response(
description="List of video playlists",
schema=VideoPlaylistListSerializer(many=True)
)
}
)
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
queryset = Video.objects.filter(status=True).order_by('-created_at')
# Search by title if search parameter is provided
search_query = self.request.query_params.get('search', None)
if search_query:
queryset = queryset.filter(title__icontains=search_query)
# Filter by category if provided
category_slug = self.request.query_params.get('category', None)
if category_slug:
queryset = queryset.filter(categories__slug=category_slug)
# Filter by collection if provided
collection_slug = self.request.query_params.get('collection', None)
if collection_slug:
queryset = queryset.filter(collections__slug=collection_slug)
is_bookmark = self.request.query_params.get('is_bookmark', '').lower()
if is_bookmark == 'true':
# Import Bookmark model here to avoid circular imports
from apps.bookmark.models import Bookmark
# Get all bookmarked playlist IDs for the current user
bookmarked_ids = Bookmark.objects.filter(
user=self.request.user,
service=Bookmark.ServiceChoices.VIDEO_PLAYLIST,
status=True
).values_list('content_id', flat=True)
# Filter playlists by these IDs
queryset = queryset.filter(id__in=bookmarked_ids)
sort = self.request.query_params.get('sort', '-created_at')
allowed_sorts = [
'created_at', '-created_at', 'view_count', '-view_count',
'title', '-title',
'total_time', '-total_time','-created_at','created_at'
]
if sort in allowed_sorts:
# Handle multiple sort fields (e.g., '-pin,-created_at')
if ',' in sort:
queryset = queryset.order_by(*sort.split(','))
else:
queryset = queryset.order_by(sort)
else:
queryset = queryset.order_by('-created_at')
return queryset
class VideoPlaylistDetailAPIView(generics.RetrieveAPIView):
serializer_class = VideoPlaylistDetailSerializer
@ -266,11 +368,11 @@ class VideoDetailAPIView(generics.RetrieveAPIView):
return super().get(request, *args, **kwargs)
def get_queryset(self):
return Video.objects.filter(status=True)
return Video.objects.filter(slug = self.kwargs.get('slug'))
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
instance.increment_view_count()
serializer = self.get_serializer(instance)
return Response(serializer.data)
# def retrieve(self, request, *args, **kwargs):
# instance = self.get_object()
# instance.increment_view_count()
# serializer = self.get_serializer(instance)
# return Response(serializer.data)
Loading…
Cancel
Save