Browse Source

references slug url

master
Mohsen Taba 5 months ago
parent
commit
8d614ef824
  1. 146
      apps/hadis/docs.py
  2. 10
      apps/hadis/models/category.py
  3. 22
      apps/hadis/serializers/reference.py
  4. 2
      apps/hadis/urls.py
  5. 3
      apps/hadis/views/category.py
  6. 24
      apps/hadis/views/reference.py

146
apps/hadis/docs.py

@ -2,7 +2,6 @@ from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi from drf_yasg import openapi
from rest_framework import status from rest_framework import status
# Swagger documentation for HadisSectListView # Swagger documentation for HadisSectListView
hadis_sect_list_swagger = swagger_auto_schema( hadis_sect_list_swagger = swagger_auto_schema(
operation_description="Get list of all active Hadis sects grouped by sect type (Shia/Sunni)", operation_description="Get list of all active Hadis sects grouped by sect type (Shia/Sunni)",
@ -1362,6 +1361,143 @@ book_authors_list_swagger = swagger_auto_schema(
} }
) )
# ============================================================================
# GET - List all book attributes
# ============================================================================
book_attributes_list_swagger = swagger_auto_schema(
operation_description="Retrieve all custom attributes for books. Optionally filter by book reference ID or attribute title.",
operation_summary="List Book Attributes",
tags=['Hadis'],
manual_parameters=[
openapi.Parameter(
'book_reference',
openapi.IN_QUERY,
description='Filter attributes by book reference ID (optional)',
type=openapi.TYPE_INTEGER,
required=False,
),
openapi.Parameter(
'title',
openapi.IN_QUERY,
description='Filter attributes by title - partial match (optional)',
type=openapi.TYPE_STRING,
required=False,
),
openapi.Parameter(
'limit',
openapi.IN_QUERY,
description='Number of results per page',
type=openapi.TYPE_INTEGER,
required=False,
),
openapi.Parameter(
'offset',
openapi.IN_QUERY,
description='Starting index for pagination',
type=openapi.TYPE_INTEGER,
required=False,
),
],
responses={
status.HTTP_200_OK: openapi.Response(
description="List of book attributes retrieved successfully",
examples={
"application/json": {
"count": 2,
"next": None,
"previous": None,
"results": [
{
"id": 1,
"title": "Number of Hadith",
"value": "7,563",
"book_reference": 1
},
{
"id": 2,
"title": "Authenticity Grade",
"value": "Sahih (Authentic)",
"book_reference": 1
}
]
}
}
),
status.HTTP_400_BAD_REQUEST: openapi.Response(
description="Invalid query parameters",
examples={
"application/json": {
"error": "Invalid book_reference ID"
}
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# ============================================================================
# POST - Create a new book attribute
# ============================================================================
book_attributes_create_swagger = swagger_auto_schema(
operation_description="Create a new custom attribute for a book. Attributes can store additional metadata about hadith books such as number of hadith, authenticity grade, or other relevant information.",
operation_summary="Create Book Attribute",
tags=['Hadis'],
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['title', 'value', 'book_reference'],
properties={
'title': openapi.Schema(
type=openapi.TYPE_STRING,
description='Attribute title/name (e.g., "Number of Hadith")',
example='Collection Type'
),
'value': openapi.Schema(
type=openapi.TYPE_STRING,
description='Attribute value (e.g., "7,563")',
example='Hadith Compilation'
),
'book_reference': openapi.Schema(
type=openapi.TYPE_INTEGER,
description='ID of the book this attribute belongs to',
example=2
),
}
),
responses={
status.HTTP_201_CREATED: openapi.Response(
description="Book attribute created successfully",
examples={
"application/json": {
"id": 3,
"title": "Collection Type",
"value": "Hadith Compilation",
"book_reference": 2
}
}
),
status.HTTP_400_BAD_REQUEST: openapi.Response(
description="Invalid input data",
examples={
"application/json": {
"title": ["This field is required."],
"value": ["This field is required."],
"book_reference": ["Invalid book reference ID."]
}
}
),
status.HTTP_401_UNAUTHORIZED: openapi.Response(
description="Authentication required - provide a valid token"
),
status.HTTP_403_FORBIDDEN: openapi.Response(
description="Permission denied - you do not have permission to create attributes"
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# Swagger documentation for BookDetailView # Swagger documentation for BookDetailView
book_detail_swagger = swagger_auto_schema( book_detail_swagger = swagger_auto_schema(
@ -1383,12 +1519,12 @@ book_detail_swagger = swagger_auto_schema(
tags=['Hadis'], tags=['Hadis'],
manual_parameters=[ manual_parameters=[
openapi.Parameter( openapi.Parameter(
'bookreference_id',
'reference_slug',
openapi.IN_PATH, openapi.IN_PATH,
description="Unique identifier of the book reference",
type=openapi.TYPE_INTEGER,
description="Unique slug of the book reference",
type=openapi.TYPE_STRING,
required=True, required=True,
example=2
example='sunan-ibn-majah'
) )
], ],
responses={ responses={

10
apps/hadis/models/category.py

@ -46,7 +46,17 @@ class HadisCategory(MPTTModel):
language = None language = None
language_id = None language_id = None
def clean(self):
super().clean()
if self.parent and self.sect_id != self.parent.sect_id:
raise ValidationError(
_('Child category must have the same sect_type as its parent. '
f'Parent sect: {self.parent.sect.sect_type}, '
f'Your sect: {self.sect.sect_type}')
)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.full_clean()
if not self.slug: if not self.slug:
base_slug = slugify(self.title, allow_unicode=True) base_slug = slugify(self.title, allow_unicode=True)
slug = base_slug slug = base_slug

22
apps/hadis/serializers/reference.py

@ -1,6 +1,6 @@
from rest_framework import serializers from rest_framework import serializers
from ..serializers import HadisListSerializer
from ..serializers import HadisListSerializer,HadisBasicSerializer
from ..models import BookReference , BookAuthor , BookReferenceImage, HadisReference , BookAttribute from ..models import BookReference , BookAuthor , BookReferenceImage, HadisReference , BookAttribute
class BookAuthorSerializer(serializers.ModelSerializer): class BookAuthorSerializer(serializers.ModelSerializer):
@ -22,7 +22,7 @@ class BookReferenceSerializer(serializers.ModelSerializer):
author = serializers.SerializerMethodField() author = serializers.SerializerMethodField()
class Meta: class Meta:
model = BookReference model = BookReference
fields = ['id','title','rate','author','description','image','volume']
fields = ['id','title','slug','rate','author','description','image','volume']
def get_author (self,obj): def get_author (self,obj):
author = obj.authors.all() author = obj.authors.all()
return [ return [
@ -56,16 +56,24 @@ class BookDetailSerializer(serializers.ModelSerializer):
source='images' source='images'
) )
hadis = HadisListSerializer(
many=True,
read_only=True,
source='hadis_references'
)
# hadis = HadisListSerializer(
# many=True,
# read_only=True,
# source='hadis_references__hadis'
# )
hadis = serializers.SerializerMethodField()
class Meta: class Meta:
model = BookReference model = BookReference
fields = ['id','title','rate','isbn','language','number_page','publisher','description','volume','slug','attribute','author','image','hadis'] fields = ['id','title','rate','isbn','language','number_page','publisher','description','volume','slug','attribute','author','image','hadis']
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
class BookReferenceSyncSerializer(serializers.ModelSerializer): class BookReferenceSyncSerializer(serializers.ModelSerializer):
"""Serializer for syncing all book reference data for offline mode""" """Serializer for syncing all book reference data for offline mode"""

2
apps/hadis/urls.py

@ -29,6 +29,6 @@ urlpatterns = [
path('narrators/<int:transmitters_id>/opinions',TransmitterOpinionView.as_view(), name='narrator-opinions'), path('narrators/<int:transmitters_id>/opinions',TransmitterOpinionView.as_view(), name='narrator-opinions'),
path('narrators/<int:transmitters_id>/original_texts',TransmitterOriginalTextView.as_view(), name='narrator-original-texts'), path('narrators/<int:transmitters_id>/original_texts',TransmitterOriginalTextView.as_view(), name='narrator-original-texts'),
path('references/',BookReferencesView.as_view(), name='references'), path('references/',BookReferencesView.as_view(), name='references'),
path('references/<int:bookreference_id>',BookDetailView.as_view(), name='reference-detail'),
path('references/<str:reference_slug>',BookDetailView.as_view(), name='reference-detail'),
path('references/attributes/',BookAttributeView.as_view(), name='book-attributes'), path('references/attributes/',BookAttributeView.as_view(), name='book-attributes'),
] ]

3
apps/hadis/views/category.py

@ -212,6 +212,8 @@ class HadisCategorySelectBySectView(ListAPIView):
def get_queryset(self): def get_queryset(self):
sect_type = self.kwargs.get('sect_type') sect_type = self.kwargs.get('sect_type')
slug = self.kwargs.get('slug') slug = self.kwargs.get('slug')
print(slug)
print(sect_type)
# Find the parent category by slug and sect_type # Find the parent category by slug and sect_type
try: try:
@ -221,6 +223,7 @@ class HadisCategorySelectBySectView(ListAPIView):
sect__is_active=True sect__is_active=True
) )
except HadisCategory.DoesNotExist: except HadisCategory.DoesNotExist:
print('not ok')
return HadisCategory.objects.none() return HadisCategory.objects.none()
# Return children of this category, filtered as before # Return children of this category, filtered as before

24
apps/hadis/views/reference.py

@ -2,7 +2,7 @@ from rest_framework.generics import ListAPIView, RetrieveAPIView,ListCreateAPIVi
from rest_framework.response import Response from rest_framework.response import Response
from ..models import BookReference , BookAuthor , BookReferenceImage, BookAttribute from ..models import BookReference , BookAuthor , BookReferenceImage, BookAttribute
from ..serializers.reference import BookAuthorSerializer, BookDetailSerializer , BookReferenceSerializer, BookReferenceSyncSerializer, BookAttributeSerializer from ..serializers.reference import BookAuthorSerializer, BookDetailSerializer , BookReferenceSerializer, BookReferenceSyncSerializer, BookAttributeSerializer
from ..docs import book_references_list_swagger, book_authors_list_swagger, book_detail_swagger, reference_sync_swagger
from ..docs import book_attributes_create_swagger, book_attributes_list_swagger, book_references_list_swagger, book_authors_list_swagger, book_detail_swagger, reference_sync_swagger
from utils.pagination import NoPagination from utils.pagination import NoPagination
@ -26,18 +26,19 @@ class BookAuthorView(ListAPIView):
class BookDetailView(RetrieveAPIView): class BookDetailView(RetrieveAPIView):
serializer_class = BookDetailSerializer serializer_class = BookDetailSerializer
lookup_field = 'id'
lookup_url_kwarg = 'bookreference_id'
lookup_field = 'slug'
lookup_url_kwarg = 'reference_slug'
@book_detail_swagger @book_detail_swagger
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
def get_queryset(self): def get_queryset(self):
return BookReference.objects.filter(id = self.kwargs['bookreference_id']).prefetch_related(
'authors__name',
'images__image',
)
return BookReference.objects.filter(slug = self.kwargs.get('reference_slug'))
# .prefetch_related(
# 'authors__name',
# 'images__image',
# )
class BookReferenceSyncView(ListAPIView): class BookReferenceSyncView(ListAPIView):
@ -84,3 +85,12 @@ class BookAttributeView(ListCreateAPIView):
queryset = BookAttribute.objects.all() queryset = BookAttribute.objects.all()
serializer_class = BookAttributeSerializer serializer_class = BookAttributeSerializer
@book_attributes_list_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
@book_attributes_create_swagger
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
Loading…
Cancel
Save