diff --git a/apps/hadis/docs.py b/apps/hadis/docs.py index 290c773..f5f1b34 100644 --- a/apps/hadis/docs.py +++ b/apps/hadis/docs.py @@ -162,71 +162,111 @@ hadis_category_tree_swagger = swagger_auto_schema( # Swagger documentation for HadisListView hadis_list_swagger = swagger_auto_schema( - operation_description="Get paginated list of Hadis for a specific category with translations based on request language", + operation_description=""" + Retrieve a paginated list of Hadis (traditions) for a specific category. + + **Key Features:** + - Returns hadis entries filtered by category ID + - Supports pagination for large datasets + - Translations are automatically provided based on the Accept-Language header + - Each hadis includes its category information, title, narrator, Arabic text, and translation + + **Usage:** + - Use this endpoint to browse hadis within a specific category + - The response includes pagination links (next/previous) for navigation + - Set the Accept-Language header to get translations in your preferred language (en, fa, ar, ur) + - Only active (status=True) hadis are returned + + **Response Structure:** + - `count`: Total number of hadis in the category + - `next`: URL for the next page (null if on last page) + - `previous`: URL for the previous page (null if on first page) + - `results`: Array of hadis objects with full details + """, operation_summary="List Hadis by Category", tags=['Hadis'], manual_parameters=[ openapi.Parameter( 'category_id', openapi.IN_PATH, - description="ID of the Hadis category", + description="Unique identifier of the Hadis category. Must be a valid category ID that exists in the system.", type=openapi.TYPE_INTEGER, - required=True + required=True, + example=1 ), openapi.Parameter( 'page', openapi.IN_QUERY, - description="Page number for pagination", + description="Page number for pagination. Starts from 1. If not provided, returns the first page.", type=openapi.TYPE_INTEGER, - required=False + required=False, + example=1 ), openapi.Parameter( 'Accept-Language', openapi.IN_HEADER, - description="Language code for translations (en, fa, ar, ur)", + description="Language code for translations. Supported codes: 'en' (English), 'fa' (Persian), 'ar' (Arabic), 'ur' (Urdu). Defaults to 'en' if not specified.", type=openapi.TYPE_STRING, required=False, - default='en' + default='en', + enum=['en', 'fa', 'ar', 'ur'] ) ], responses={ status.HTTP_200_OK: openapi.Response( - description="Paginated list of hadis", + description="Successfully retrieved paginated list of hadis for the specified category", examples={ "application/json": { "count": 150, - "next": "http://example.com/api/hadis/category/1/hadis/?page=2", + "next": "http://example.com/api/hadis/category/1/?page=2", "previous": None, "results": [ { "id": 1, "number": 1, - "title": "The first hadis about faith", + "title": "The Opening", + "title_narrator": "From Abu Hurairah", + "text": "إنما الأعمال بالنيات وإنما لكل امرئ ما نوى", + "translation": "Actions are but by intention, and every man shall have only what he intended", "category": { "id": 1, - "title": "Book of Faith" + "title": "Book of Faith", + "slug": "book-of-faith", + "source_type": "hadith", + "sect_type": "sunni" }, - "translation": "This is the English translation of the hadis" + "share_link": "http://example.com/hadis/1" }, { "id": 2, "number": 2, - "title": "The second hadis about prayer", + "title": "The Second Hadith", + "title_narrator": "From Umar ibn al-Khattab", + "text": "بينما نحن عند رسول الله صلى الله عليه وسلم ذات يوم", + "translation": "While we were sitting with the Messenger of Allah (peace be upon him) one day", "category": { "id": 1, - "title": "Book of Faith" + "title": "Book of Faith", + "slug": "book-of-faith", + "source_type": "hadith", + "sect_type": "sunni" }, - "translation": "This is the English translation of the second hadis" + "share_link": "http://example.com/hadis/2" } ] } } ), status.HTTP_404_NOT_FOUND: openapi.Response( - description="Category not found" + description="The specified category ID does not exist or the category has no active hadis", + examples={ + "application/json": { + "detail": "Not found." + } + } ), status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( - description="Internal server error" + description="Internal server error occurred while processing the request" ) } ) @@ -256,7 +296,8 @@ hadis_basic_swagger = swagger_auto_schema( "title_narrator": "From Abu Hurairah", "text": "Actions are but by intention...", "translation": "Actions are but by intention...", - "share_link": "http://example.com/hadis/1" + "share_link": "http://example.com/hadis/1", + 'explanation': "This hadith emphasizes the importance of intention in all actions...", } } ), @@ -453,7 +494,31 @@ hadis_transmitters_swagger = swagger_auto_schema( ) hadis_corrections_swagger = swagger_auto_schema( - operation_description="Get all corrections for a specific hadis including translation corrections and scholarly improvements", + operation_description=""" + Retrieve all corrections, improvements, and scholarly notes for a specific hadis. + + **Key Features:** + - Returns all corrections associated with a hadis + - Includes translation corrections in multiple languages + - Provides scholarly improvements and clarifications + - Useful for understanding updates and refinements to hadis content + + **Usage:** + - Use this endpoint to get corrections and improvements for a hadis + - Corrections may include updated translations, authenticity clarifications, or scholarly notes + - The `translation` field contains multilingual corrections (typically JSON format) + - Each correction has a title and description explaining the nature of the correction + + **Response Structure:** + - `hadis_id`: The ID of the hadis these corrections belong to + - `corrections_count`: Total number of corrections available + - `corrections`: Array of correction objects with details + + **Note:** + - If no corrections exist, the corrections array will be empty + - Corrections are ordered by creation date (newest first) + - Translation corrections may be in JSON format with language codes as keys + """, operation_summary="Get Hadis Corrections", operation_id="getHadisCorrections", tags=['Hadis'], @@ -461,14 +526,15 @@ hadis_corrections_swagger = swagger_auto_schema( openapi.Parameter( 'hadis_id', openapi.IN_PATH, - description="ID of the hadis", + description="Unique identifier of the hadis. Must be a valid hadis ID that exists in the system. Only active hadis (status=True) are accessible.", type=openapi.TYPE_INTEGER, - required=True + required=True, + example=1 ) ], responses={ status.HTTP_200_OK: openapi.Response( - description="Hadis corrections information", + description="Successfully retrieved corrections for the specified hadis", examples={ "application/json": { "hadis_id": 1, @@ -477,21 +543,23 @@ hadis_corrections_swagger = swagger_auto_schema( { "id": 1, "title": "Translation Correction", - "description": "Corrected translation for better accuracy", + "description": "Updated translation for better accuracy and clarity. The previous translation was slightly ambiguous in the context of intention and action.", "translation": { - "en": "Actions are judged by intentions...", - "ar": "إنما الأعمال بالنيات...", - "fa": "اعمال به نیت ها قضاوت می شود..." + "en": "Actions are judged by intentions, and every person will have what they intended", + "ar": "إنما الأعمال بالنيات وإنما لكل امرئ ما نوى", + "fa": "اعمال به نیت ها قضاوت می شود و هر کس آنچه را که قصد کرده است خواهد داشت", + "ur": "اعمال نیتوں کے مطابق ہیں اور ہر شخص کو وہی ملے گا جس کا اس نے ارادہ کیا" } }, { "id": 2, "title": "Authenticity Clarification", - "description": "Additional notes on hadith authenticity", + "description": "Additional scholarly notes on the authenticity and grading of this hadith. This hadith is considered authentic (sahih) by consensus of scholars.", "translation": { - "en": "This hadith is authentic according to...", - "ar": "هذا الحديث صحيح حسب...", - "fa": "این حدیث صحیح است طبق..." + "en": "This hadith is authentic (sahih) according to the consensus of scholars including Imam Bukhari and Imam Muslim", + "ar": "هذا الحديث صحيح حسب إجماع العلماء بما في ذلك الإمام البخاري والإمام مسلم", + "fa": "این حدیث طبق اجماع علماء از جمله امام بخاری و امام مسلم صحیح است", + "ur": "یہ حدیث علماء کے اجماع کے مطابق صحیح ہے جن میں امام بخاری اور امام مسلم شامل ہیں" } } ] @@ -499,10 +567,15 @@ hadis_corrections_swagger = swagger_auto_schema( } ), status.HTTP_404_NOT_FOUND: openapi.Response( - description="Hadis not found" + description="The specified hadis ID does not exist or the hadis is not active", + examples={ + "application/json": { + "detail": "Not found." + } + } ), status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( - description="Internal server error" + description="Internal server error occurred while processing the request" ) } ) @@ -759,35 +832,6 @@ transmitter_detail_swagger = swagger_auto_schema( "in_sahih_muslim": True, "description": "Imam Abu Daud, compiler of Sunan Abu Daud", "thumbnail": "http://example.com/media/transmitters/abu_daud.jpg", - "opinions": [ - { - "id": 1, - "scholar_name": "Ibn Hajar al-Asqalani", - "opinion_text": "Abu Daud was a reliable and trustworthy narrator", - "status": "confirmed", - "created_at": "2024-01-01T00:00:00Z", - "updated_at": "2024-01-01T00:00:00Z" - } - ], - "hadis_transmissions": [ - { - "id": 1, - "hadis": { - "id": 1001, - "number": 1, - "title": "The first hadith", - "category": { - "id": 1, - "title": "Book of Faith" - }, - "translation": "Actions are by intentions" - }, - "order": 1, - "status": "reliable", - "narrator_layer": 1, - "created_at": "2024-01-01T00:00:00Z" - } - ] } } ), @@ -862,22 +906,231 @@ transmitter_sync_swagger = swagger_auto_schema( } ) +# Swagger documentation for TransmitterOpinionView +transmitter_opinion_swagger = swagger_auto_schema( + operation_description=""" + Retrieve all scholarly opinions about a specific transmitter (narrator). + + **Key Features:** + - Returns all opinions from various scholars about the transmitter's reliability and character + - Includes opinion status (confirmed, mixed, rejected) + - Provides detailed opinion text from each scholar + - Useful for understanding the scholarly consensus on a narrator's reliability + + **Usage:** + - Use this endpoint to get scholarly assessments of a transmitter + - Opinions help determine the reliability and authenticity of narrations + - The `status` field indicates whether the opinion is confirmed, mixed, or rejected + - Each opinion includes the scholar's name and their detailed assessment + + **Response Structure:** + - Returns an array of opinion objects + - Each opinion includes scholar name, opinion text, status, and timestamps + - Opinions are ordered by creation date (newest first) + + **Opinion Status Values:** + - `confirmed`: The opinion is confirmed and widely accepted + - `mixed`: There are mixed views about this opinion + - `rejected`: The opinion has been rejected or is not widely accepted + """, + operation_summary="Get Transmitter Opinions", + operation_id="getTransmitterOpinions", + tags=['Hadis'], + manual_parameters=[ + openapi.Parameter( + 'transmitters_id', + openapi.IN_PATH, + description="Unique identifier of the transmitter (narrator). Must be a valid transmitter ID that exists in the system.", + type=openapi.TYPE_INTEGER, + required=True, + example=56 + ) + ], + responses={ + status.HTTP_200_OK: openapi.Response( + description="Successfully retrieved all scholarly opinions for the specified transmitter", + examples={ + "application/json": [ + { + "id": 1, + "transmitter": 56, + "scholar_name": "Ibn Hajar al-Asqalani", + "opinion_text": "He was a reliable and trustworthy narrator. His narrations are accepted and he is considered among the reliable transmitters of hadith. He had good memory and was known for his accuracy in transmission.", + "status": "confirmed", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + }, + { + "id": 2, + "transmitter": 56, + "scholar_name": "Imam al-Dhahabi", + "opinion_text": "A reliable narrator with good character. His narrations are generally accepted, though some scholars have noted minor issues in certain chains of transmission.", + "status": "mixed", + "created_at": "2024-01-14T14:20:00Z", + "updated_at": "2024-01-14T14:20:00Z" + }, + { + "id": 3, + "transmitter": 56, + "scholar_name": "Ibn Ma'in", + "opinion_text": "Trustworthy and reliable. His narrations are sound and he is considered among the reliable transmitters.", + "status": "confirmed", + "created_at": "2024-01-13T09:15:00Z", + "updated_at": "2024-01-13T09:15:00Z" + } + ] + } + ), + status.HTTP_404_NOT_FOUND: openapi.Response( + description="The specified transmitter ID does not exist", + examples={ + "application/json": { + "detail": "Not found." + } + } + ), + status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( + description="Internal server error occurred while processing the request" + ) + } +) + +# Swagger documentation for TransmitterOriginalTextView +transmitter_original_text_swagger = swagger_auto_schema( + operation_description=""" + Retrieve all original texts associated with a specific transmitter (narrator). + + **Key Features:** + - Returns all original texts (writings, sayings, or works) attributed to the transmitter + - Includes original Arabic text and translations in multiple languages + - Provides shareable links for each text + - Useful for accessing the original works and writings of narrators + + **Usage:** + - Use this endpoint to get original texts written or attributed to a transmitter + - Original texts may include their writings, sayings, or scholarly works + - The `translation` field contains multilingual translations (typically JSON format) + - Each text has a shareable link for easy sharing + + **Response Structure:** + - Returns an array of original text objects + - Each text includes title, original text, translations, and share link + - Texts are ordered by creation date (newest first) + + **Translation Format:** + - The translation field is typically a JSON array or object + - May contain translations in multiple languages + - Format may vary based on how translations are stored + """, + operation_summary="Get Transmitter Original Texts", + operation_id="getTransmitterOriginalTexts", + tags=['Hadis'], + manual_parameters=[ + openapi.Parameter( + 'transmitters_id', + openapi.IN_PATH, + description="Unique identifier of the transmitter (narrator). Must be a valid transmitter ID that exists in the system.", + type=openapi.TYPE_INTEGER, + required=True, + example=56 + ) + ], + responses={ + status.HTTP_200_OK: openapi.Response( + description="Successfully retrieved all original texts for the specified transmitter", + examples={ + "application/json": [ + { + "id": 1, + "title": "On the Importance of Intention", + "text": "إنما الأعمال بالنيات وإنما لكل امرئ ما نوى. فمن كانت هجرته إلى الله ورسوله فهجرته إلى الله ورسوله، ومن كانت هجرته لدنيا يصيبها أو امرأة ينكحها فهجرته إلى ما هاجر إليه", + "translation": [ + { + "language_code": "en", + "title": "Actions are but by intention, and every person will have what they intended. So whoever emigrated for Allah and His Messenger, then his emigration is for Allah and His Messenger. And whoever emigrated for worldly gain or to marry a woman, then his emigration is for that which he emigrated." + }, + { + "language_code": "fa", + "title": "اعمال به نیت ها است و هر کس آنچه را که قصد کرده است خواهد داشت. پس هر کس برای خدا و پیامبرش هجرت کند، هجرت او برای خدا و پیامبرش است. و هر کس برای منافع دنیوی یا ازدواج با زنی هجرت کند، هجرت او برای همان چیزی است که برای آن هجرت کرده است." + } + ], + "share_link": "http://example.com/narrators/56/texts/1" + }, + { + "id": 2, + "title": "On Knowledge and Learning", + "text": "طلب العلم فريضة على كل مسلم ومسلمة", + "translation": [ + { + "language_code": "en", + "title": "Seeking knowledge is obligatory upon every Muslim, male and female" + }, + { + "language_code": "fa", + "title": "طلب علم بر هر مسلمان و مسلمانی واجب است" + } + ], + "share_link": "http://example.com/narrators/56/texts/2" + } + ] + } + ), + status.HTTP_404_NOT_FOUND: openapi.Response( + description="The specified transmitter ID does not exist", + examples={ + "application/json": { + "detail": "Not found." + } + } + ), + status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( + description="Internal server error occurred while processing the request" + ) + } +) + # Swagger documentation for BookReferencesView book_references_list_swagger = swagger_auto_schema( - operation_description="Get list of all book references used in hadith studies including their metadata, images, and volume counts", + operation_description=""" + Retrieve a comprehensive list of all book references used in hadith studies. + + **Key Features:** + - Returns all book references in the system + - Includes metadata such as title, description, rating, and author information + - Provides book cover images and volume counts + - Useful for browsing available reference books + + **Usage:** + - Use this endpoint to get an overview of all available reference books + - The `rate` field indicates the book's rating (typically 0-5) + - The `volume_count` shows how many volumes the book has + - The `image` array contains book cover images and related images + - The `author` field contains the primary author's name + + **Response Structure:** + - Returns an array of book reference objects + - Each book includes basic information, images, and volume count + - Books are typically ordered by ID or title + + **Note:** + - Some books may have multiple volumes (indicated by `volume_count`) + - Images array may be empty if no images are available + - The author field contains the name of the primary author + """, operation_summary="List Book References", tags=['Hadis'], responses={ status.HTTP_200_OK: openapi.Response( - description="List of all book references", + description="Successfully retrieved list of all book references", examples={ "application/json": [ { "id": 1, "title": "Sahih al-Bukhari", - "description": "The most authentic collection of hadith compiled by Imam Bukhari", + "description": "The most authentic collection of hadith compiled by Imam Bukhari. This collection is considered the most authentic book after the Quran and contains over 7,000 hadiths.", "rate": 5.0, + "author": "Muhammad ibn Isma'il al-Bukhari", "image": [ { "id": 1, @@ -885,6 +1138,13 @@ book_references_list_swagger = swagger_auto_schema( "order": 1, "description": "Front cover of Sahih al-Bukhari", "created_at": "2024-01-01T00:00:00Z" + }, + { + "id": 2, + "image": "http://example.com/media/books/bukhari_back.jpg", + "order": 2, + "description": "Back cover of Sahih al-Bukhari", + "created_at": "2024-01-01T00:00:00Z" } ], "volume_count": 9 @@ -892,16 +1152,34 @@ book_references_list_swagger = swagger_auto_schema( { "id": 2, "title": "Sahih Muslim", - "description": "The second most authentic collection of hadith compiled by Imam Muslim", + "description": "The second most authentic collection of hadith compiled by Imam Muslim ibn al-Hajjaj. This collection is highly regarded and contains over 7,000 hadiths.", "rate": 4.9, - "image": [], + "author": "Muslim ibn al-Hajjaj al-Qushayri", + "image": [ + { + "id": 3, + "image": "http://example.com/media/books/muslim_cover.jpg", + "order": 1, + "description": "Front cover of Sahih Muslim", + "created_at": "2024-01-01T00:00:00Z" + } + ], "volume_count": 7 + }, + { + "id": 3, + "title": "Sunan Abu Daud", + "description": "A collection of hadith compiled by Imam Abu Daud. Contains approximately 4,800 hadiths focusing on legal rulings.", + "rate": 4.8, + "author": "Abu Daud Sulaiman ibn al-Ash'ath", + "image": [], + "volume_count": 4 } ] } ), status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( - description="Internal server error" + description="Internal server error occurred while processing the request" ) } ) @@ -997,26 +1275,55 @@ book_authors_list_swagger = swagger_auto_schema( # Swagger documentation for BookDetailView book_detail_swagger = swagger_auto_schema( - operation_description="Get detailed information about a specific book reference including authors, images, and related hadiths", + operation_description=""" + Retrieve detailed information about a specific book reference. + + **Key Features:** + - Returns comprehensive details about a book reference + - Includes publication information (ISBN, year, pages, language) + - Provides author information and book images + - Lists all hadis referenced from this book + - Includes volume information and rating + + **Usage:** + - Use this endpoint to get complete details about a specific book + - The `hadis` array contains all hadis entries that reference this book + - The `author` array may contain multiple authors if applicable + - The `image` array includes all book-related images (covers, pages, etc.) + - Publication details help identify specific editions + + **Response Structure:** + - Complete book metadata including all fields from the book reference model + - Related hadis entries with basic information + - Author and image information + - Volume count for multi-volume books + + **Note:** + - The `hadis` field contains hadis entries that are referenced in this book + - Each hadis includes its category information and translation + - Images are ordered by the `order` field + - The `volume_count` field shows how many volumes this book has + """, operation_summary="Get Book Reference Details", tags=['Hadis'], manual_parameters=[ openapi.Parameter( 'bookreference_id', openapi.IN_PATH, - description="ID of the book reference", + description="Unique identifier of the book reference. Must be a valid book reference ID that exists in the system.", type=openapi.TYPE_INTEGER, - required=True + required=True, + example=1 ) ], responses={ status.HTTP_200_OK: openapi.Response( - description="Detailed book reference information", + description="Successfully retrieved detailed information about the book reference", examples={ "application/json": { "id": 1, "title": "Sahih al-Bukhari", - "description": "The most authentic collection of hadith compiled by Imam Bukhari", + "description": "The most authentic collection of hadith compiled by Imam Bukhari. This collection is considered the most authentic book after the Quran and contains over 7,000 hadiths carefully selected from hundreds of thousands of narrations.", "language": "Arabic", "isbn": "978-1234567890", "volume": "9 volumes", @@ -1040,28 +1347,63 @@ book_detail_swagger = swagger_auto_schema( "order": 1, "description": "Front cover of Sahih al-Bukhari", "created_at": "2024-01-01T00:00:00Z" + }, + { + "id": 2, + "image": "http://example.com/media/books/bukhari_title_page.jpg", + "order": 2, + "description": "Title page of Sahih al-Bukhari", + "created_at": "2024-01-01T00:00:00Z" } ], "hadis": [ { "id": 1, "number": 1, - "title": "The first hadith about faith", + "title": "The Opening", + "title_narrator": "From Abu Hurairah", + "text": "إنما الأعمال بالنيات وإنما لكل امرئ ما نوى", + "translation": "Actions are but by intention, and every person will have what they intended", + "category": { + "id": 1, + "title": "Book of Faith", + "slug": "book-of-faith", + "source_type": "hadith", + "sect_type": "sunni" + }, + "share_link": "http://example.com/hadis/1" + }, + { + "id": 2, + "number": 2, + "title": "The Second Hadith", + "title_narrator": "From Umar ibn al-Khattab", + "text": "بينما نحن عند رسول الله صلى الله عليه وسلم ذات يوم", + "translation": "While we were sitting with the Messenger of Allah (peace be upon him) one day", "category": { "id": 1, - "title": "Book of Faith" + "title": "Book of Faith", + "slug": "book-of-faith", + "source_type": "hadith", + "sect_type": "sunni" }, - "translation": "Actions are by intentions" + "share_link": "http://example.com/hadis/2" } - ] + ], + "volume_count": 9 } } ), status.HTTP_404_NOT_FOUND: openapi.Response( - description="Book reference not found" + description="The specified book reference ID does not exist", + examples={ + "application/json": { + "detail": "Not found." + } + } ), status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( - description="Internal server error" + description="Internal server error occurred while processing the request" ) } ) @@ -1069,12 +1411,38 @@ book_detail_swagger = swagger_auto_schema( # Swagger documentation for CategoriesView categories_list_swagger = swagger_auto_schema( - operation_description="Get list of all hadith categories with their associated sect information", + operation_description=""" + Retrieve a comprehensive list of all Hadis categories in the system. + + **Key Features:** + - Returns all categories regardless of sect type or source type + - Includes hierarchical information (children count) + - Provides category metadata including sect association, source type, and description + - Shows whether categories have direct hadis entries or child categories + + **Usage:** + - Use this endpoint to get an overview of all available categories + - The `children_count` field indicates how many subcategories exist + - The `has_hadis` field shows if the category directly contains hadis (no children) + - The `hadis_count` field shows the total number of hadis in this category + + **Response Fields:** + - `id`: Unique category identifier + - `title`: Category name + - `sect_id`: Associated sect ID + - `sect_type`: Type of Islamic sect (shia/sunni) + - `source_type`: Type of source material (quran, hadith, history, fatwa, quote) + - `description`: Detailed description of the category + - `slug`: URL-friendly identifier + - `children_count`: Number of direct child categories + - `has_hadis`: Boolean indicating if category has direct hadis entries + - `hadis_count`: Total number of hadis in this category + """, operation_summary="List All Categories", tags=['Hadis'], responses={ status.HTTP_200_OK: openapi.Response( - description="List of all hadith categories", + description="Successfully retrieved list of all hadith categories", examples={ "application/json": [ { @@ -1083,11 +1451,11 @@ categories_list_swagger = swagger_auto_schema( "sect_id": 1, "sect_type": "sunni", "source_type": "hadith", - "description": "Hadiths related to Islamic faith and beliefs", - "order": 1, + "description": "Hadiths related to Islamic faith and beliefs, including articles of faith, belief in Allah, angels, books, messengers, and the Last Day", "slug": "book-of-faith", - "xmind_file": "http://example.com/media/xmind/faith.xmind", - "children_count": 3 + "children_count": 3, + "has_hadis": False, + "hadis_count": 0 }, { "id": 2, @@ -1095,17 +1463,29 @@ categories_list_swagger = swagger_auto_schema( "sect_id": 1, "sect_type": "sunni", "source_type": "hadith", - "description": "Hadiths about salah (prayer) and related rulings", - "order": 2, + "description": "Hadiths about salah (prayer) and related rulings, including prayer times, conditions, and etiquettes", "slug": "book-of-prayer", - "xmind_file": None, - "children_count": 0 + "children_count": 0, + "has_hadis": True, + "hadis_count": 45 + }, + { + "id": 10, + "title": "Tafsir of Surah Al-Fatiha", + "sect_id": 2, + "sect_type": "shia", + "source_type": "quran", + "description": "Commentary and interpretation of the opening chapter of the Quran", + "slug": "tafsir-al-fatiha", + "children_count": 0, + "has_hadis": True, + "hadis_count": 12 } ] } ), status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( - description="Internal server error" + description="Internal server error occurred while processing the request" ) } ) @@ -1113,22 +1493,42 @@ categories_list_swagger = swagger_auto_schema( # Swagger documentation for CategoriesBySectView categories_by_sect_swagger = swagger_auto_schema( - operation_description="Get list of hadith categories filtered by sect type (shia or sunni)", + operation_description=""" + Retrieve a list of Hadis categories filtered by Islamic sect type. + + **Key Features:** + - Filters categories by sect type (shia or sunni) + - Returns all categories belonging to the specified sect + - Includes hierarchical information and hadis counts + - Useful for building sect-specific category navigation + + **Usage:** + - Use this endpoint to get categories for a specific Islamic sect + - The `sect_type` parameter must be either 'shia' or 'sunni' + - Results are ordered by the category's order field + - Use the `children_count` to build hierarchical navigation + + **Response Structure:** + - Returns an array of category objects + - Each category includes sect information, source type, and hierarchical data + - The `has_hadis` field indicates if the category can be used to fetch hadis directly + """, operation_summary="List Categories by Sect", tags=['Hadis'], manual_parameters=[ openapi.Parameter( 'sect_type', openapi.IN_PATH, - description="Type of Islamic sect (shia or sunni)", + description="Type of Islamic sect. Must be either 'shia' (Shi'a Islam) or 'sunni' (Sunni Islam). This filters categories to only those belonging to the specified sect.", type=openapi.TYPE_STRING, enum=['shia', 'sunni'], - required=True + required=True, + example='sunni' ) ], responses={ status.HTTP_200_OK: openapi.Response( - description="List of hadith categories filtered by sect type", + description="Successfully retrieved list of categories for the specified sect type", examples={ "application/json": [ { @@ -1137,11 +1537,11 @@ categories_by_sect_swagger = swagger_auto_schema( "sect_id": 1, "sect_type": "sunni", "source_type": "hadith", - "description": "Hadiths related to Islamic faith and beliefs", - "order": 1, + "description": "Hadiths related to Islamic faith and beliefs, including articles of faith, belief in Allah, angels, books, messengers, and the Last Day", "slug": "book-of-faith", - "xmind_file": "http://example.com/media/xmind/faith.xmind", - "children_count": 3 + "children_count": 3, + "has_hadis": False, + "hadis_count": 0 }, { "id": 2, @@ -1149,17 +1549,37 @@ categories_by_sect_swagger = swagger_auto_schema( "sect_id": 1, "sect_type": "sunni", "source_type": "hadith", - "description": "Hadiths about salah (prayer) and related rulings", - "order": 2, + "description": "Hadiths about salah (prayer) and related rulings, including prayer times, conditions, and etiquettes", "slug": "book-of-prayer", - "xmind_file": None, - "children_count": 0 + "children_count": 0, + "has_hadis": True, + "hadis_count": 45 + }, + { + "id": 3, + "title": "Book of Zakat", + "sect_id": 1, + "sect_type": "sunni", + "source_type": "hadith", + "description": "Hadiths about zakat (obligatory charity) and its rulings", + "slug": "book-of-zakat", + "children_count": 2, + "has_hadis": False, + "hadis_count": 0 } ] } ), + status.HTTP_400_BAD_REQUEST: openapi.Response( + description="Invalid sect_type parameter. Must be 'shia' or 'sunni'", + examples={ + "application/json": { + "detail": "Invalid sect type. Must be 'shia' or 'sunni'." + } + } + ), status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( - description="Internal server error" + description="Internal server error occurred while processing the request" ) } ) @@ -1167,7 +1587,28 @@ categories_by_sect_swagger = swagger_auto_schema( # Swagger documentation for HadisCategoryTreeBySectView categories_tree_by_sect_swagger = swagger_auto_schema( - operation_description="Retrieve child categories of a specific parent category (identified by slug) within a given Islamic sect type", + operation_description=""" + Retrieve child categories of a specific parent category within a given Islamic sect type. + + **Key Features:** + - Returns direct children of a parent category identified by slug + - Filters by sect type to ensure correct sect association + - Provides hierarchical navigation through category tree + - Includes information about whether categories have hadis or further children + + **Usage:** + - Use this endpoint to navigate through the category hierarchy + - The `slug` parameter identifies the parent category + - The `sect_type` ensures categories belong to the correct sect + - Use `children_count` to determine if a category has subcategories + - Use `has_hadis` to determine if you can fetch hadis directly from this category + + **Navigation Flow:** + 1. Start with root categories (use categories// endpoint) + 2. Use the slug from a category to get its children + 3. Continue navigating down the tree until you reach a category with `has_hadis: true` + 4. Use that category's ID to fetch hadis using the category// endpoint + """, operation_summary="Get Category Children by Sect and Slug", operation_id="getCategoryChildrenBySectAndSlug", tags=['Hadis'], @@ -1175,56 +1616,72 @@ categories_tree_by_sect_swagger = swagger_auto_schema( openapi.Parameter( 'sect_type', openapi.IN_PATH, - description="Type of Islamic sect (shia or sunni)", + description="Type of Islamic sect. Must be 'shia' or 'sunni'. This ensures categories belong to the correct sect.", type=openapi.TYPE_STRING, enum=['shia', 'sunni'], - required=True + required=True, + example='shia' ), openapi.Parameter( 'slug', openapi.IN_PATH, - description="URL slug of the parent category", + description="URL-friendly slug identifier of the parent category. This is used to locate the parent category whose children you want to retrieve. The slug is typically derived from the category title.", type=openapi.TYPE_STRING, - required=True + required=True, + example='book-of-faith' ) ], responses={ status.HTTP_200_OK: openapi.Response( - description="List of child categories belonging to the specified parent category (identified by slug) within the given sect type", + description="Successfully retrieved list of child categories for the specified parent category", examples={ "application/json": [ { "id": 330, - "title": "Толкование суры Аль-Фатиха", + "title": "Tafsir of Surah Al-Fatiha", "source_type": "quran", - "slug": "-1", + "slug": "tafsir-al-fatiha", "sect_id": 20, "sect_type": "shia", - "children_count": 0 + "children_count": 0, + "has_hadis": True, + "hadis_count": 15 }, { "id": 331, - "title": "Толкование суры Аль-Бакара", + "title": "Tafsir of Surah Al-Baqarah", "source_type": "quran", - "slug": "-19", + "slug": "tafsir-al-baqarah", "sect_id": 20, "sect_type": "shia", - "children_count": 0 + "children_count": 0, + "has_hadis": True, + "hadis_count": 28 }, { "id": 332, - "title": "Толкование суры Аль Имран", + "title": "Tafsir of Surah Al-Imran", "source_type": "quran", - "slug": "-33", + "slug": "tafsir-al-imran", "sect_id": 20, "sect_type": "shia", - "children_count": 0 + "children_count": 0, + "has_hadis": True, + "hadis_count": 22 } ] } ), + status.HTTP_404_NOT_FOUND: openapi.Response( + description="Parent category with the specified slug not found in the given sect type", + examples={ + "application/json": { + "detail": "No categories found for the specified slug and sect type." + } + } + ), status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( - description="Internal server error" + description="Internal server error occurred while processing the request" ) } ) @@ -1232,7 +1689,34 @@ categories_tree_by_sect_swagger = swagger_auto_schema( # Swagger documentation for HadisCategoryTreeBySectSourceView categories_tree_by_sect_source_swagger = swagger_auto_schema( - operation_description="Retrieve child categories of a specific parent category (identified by slug) within a given Islamic sect type, additionally filtered by source material type", + operation_description=""" + Retrieve child categories of a specific parent category, filtered by sect type and source material type. + + **Key Features:** + - Returns direct children of a parent category identified by slug + - Filters by both sect type and source type for precise navigation + - Useful for filtering categories by source material (Quran, Hadith, History, Fatwa, Quote) + - Provides hierarchical navigation with source-specific filtering + + **Usage:** + - Use this endpoint when you need to filter categories by source material type + - The `source_type` parameter allows filtering by: 'quran', 'hadith', 'history', 'fatwa', or 'quote' + - This is useful for building source-specific category navigation + - Combine with sect type to get categories for a specific sect and source combination + + **Source Types:** + - `quran`: Categories related to Quranic commentary and interpretation + - `hadith`: Categories containing prophetic traditions + - `history`: Historical accounts and narratives + - `fatwa`: Legal opinions and religious rulings + - `quote`: Quotations and sayings + + **Navigation Flow:** + 1. Start with root categories filtered by sect and source type + 2. Use the slug from a category to get its children (with same source type) + 3. Continue until you reach a category with `has_hadis: true` + 4. Use that category's ID to fetch hadis + """, operation_summary="Get Category Children by Sect, Slug and Source", operation_id="getCategoryChildrenBySectSlugAndSource", tags=['Hadis'], @@ -1240,67 +1724,81 @@ categories_tree_by_sect_source_swagger = swagger_auto_schema( openapi.Parameter( 'sect_type', openapi.IN_PATH, - description="Type of Islamic sect (shia or sunni)", + description="Type of Islamic sect. Must be 'shia' or 'sunni'. Ensures categories belong to the correct sect.", type=openapi.TYPE_STRING, enum=['shia', 'sunni'], - required=True + required=True, + example='shia' ), openapi.Parameter( 'slug', openapi.IN_PATH, - description="URL slug of the parent category", + description="URL-friendly slug identifier of the parent category. Used to locate the parent category whose children you want to retrieve.", type=openapi.TYPE_STRING, - required=True + required=True, + example='quran-commentary' ), openapi.Parameter( 'source_type', openapi.IN_PATH, - description="Type of source material (quran, hadith, history, fatwa, quote)", + description="Type of source material. Filters children to only those matching this source type. Options: 'quran' (Quranic commentary), 'hadith' (Prophetic traditions), 'history' (Historical accounts), 'fatwa' (Legal opinions), 'quote' (Quotations).", type=openapi.TYPE_STRING, enum=['quran', 'hadith', 'history', 'fatwa', 'quote'], - required=True + required=True, + example='quran' ) ], responses={ status.HTTP_200_OK: openapi.Response( - description="List of child categories belonging to the specified parent category (identified by slug) within the given sect type, additionally filtered by source type", + description="Successfully retrieved list of child categories filtered by sect type and source type", examples={ "application/json": [ { "id": 330, - "title": "Толкование суры Аль-Фатиха", + "title": "Tafsir of Surah Al-Fatiha", "source_type": "quran", - "slug": "-1", + "slug": "tafsir-al-fatiha", "sect_id": 20, "sect_type": "shia", "children_count": 0, - "has_hadis": False + "has_hadis": True, + "hadis_count": 15 }, { "id": 331, - "title": "Толкование суры Аль-Бакара", + "title": "Tafsir of Surah Al-Baqarah", "source_type": "quran", - "slug": "-19", + "slug": "tafsir-al-baqarah", "sect_id": 20, "sect_type": "shia", "children_count": 0, - "has_hadis": False + "has_hadis": True, + "hadis_count": 28 }, { "id": 332, - "title": "Толкование суры Аль Имран", + "title": "Tafsir of Surah Al-Imran", "source_type": "quran", - "slug": "-33", + "slug": "tafsir-al-imran", "sect_id": 20, "sect_type": "shia", "children_count": 0, - "has_hadis": False + "has_hadis": True, + "hadis_count": 22 } ] } ), + status.HTTP_404_NOT_FOUND: openapi.Response( + description="Parent category with the specified slug not found, or no children exist with the specified source type", + examples={ + "application/json": { + "detail": "No categories found matching the specified criteria." + } + } + ), status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( - description="Internal server error" + description="Internal server error occurred while processing the request" ) } ) \ No newline at end of file diff --git a/apps/hadis/migrations/0034_hadiscorrection_share_link.py b/apps/hadis/migrations/0034_hadiscorrection_share_link.py new file mode 100644 index 0000000..871cf59 --- /dev/null +++ b/apps/hadis/migrations/0034_hadiscorrection_share_link.py @@ -0,0 +1,19 @@ +# Generated by Django 5.2.9 on 2025-12-14 10:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("hadis", "0033_hadiscorrection"), + ] + + operations = [ + migrations.AddField( + model_name="hadiscorrection", + name="share_link", + field=models.CharField( + blank=True, max_length=255, null=True, verbose_name="share link" + ), + ), + ] diff --git a/apps/hadis/migrations/0035_transmitteroriginaltext.py b/apps/hadis/migrations/0035_transmitteroriginaltext.py new file mode 100644 index 0000000..063edea --- /dev/null +++ b/apps/hadis/migrations/0035_transmitteroriginaltext.py @@ -0,0 +1,53 @@ +# Generated by Django 5.2.9 on 2025-12-14 11:47 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("hadis", "0034_hadiscorrection_share_link"), + ] + + operations = [ + migrations.CreateModel( + name="TransmitterOriginalText", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "title", + models.CharField( + blank=True, max_length=255, null=True, verbose_name="title" + ), + ), + ("text", models.TextField(verbose_name="text")), + ( + "translation", + models.JSONField(default=list, verbose_name="translation"), + ), + ( + "share_link", + models.CharField( + blank=True, max_length=255, null=True, verbose_name="share link" + ), + ), + ( + "transmitter", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="originaltextes", + to="hadis.transmitters", + verbose_name="transmitter", + ), + ), + ], + ), + ] diff --git a/apps/hadis/models/hadis.py b/apps/hadis/models/hadis.py index e7cebf5..8db81fa 100644 --- a/apps/hadis/models/hadis.py +++ b/apps/hadis/models/hadis.py @@ -212,6 +212,7 @@ class HadisCorrection(models.Model): translation = models.JSONField(verbose_name=_("translation"), default=list) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("created at")) updated_at = models.DateTimeField(auto_now=True, verbose_name=_("updated at")) + share_link = models.CharField(max_length=255, verbose_name=_('share link'), null=True, blank=True) class Meta: verbose_name = _("Hadis Correction") diff --git a/apps/hadis/models/transmitter.py b/apps/hadis/models/transmitter.py index 333ad4a..45bf388 100644 --- a/apps/hadis/models/transmitter.py +++ b/apps/hadis/models/transmitter.py @@ -5,6 +5,7 @@ from django.utils.translation import gettext_lazy as _ from filer.fields.image import FilerImageField + class NarratorLayer(models.Model): """ Model for narrator layers/classes (Tabaqat) @@ -206,3 +207,18 @@ class TransmitterOpinion(models.Model): def __str__(self): return f"{self.scholar_name}'s opinion on {self.transmitter.full_name} ({self.status})" + +class TransmitterOriginalText(models.Model): + transmitter = models.ForeignKey( + Transmitters, + on_delete=models.CASCADE, + verbose_name=_('transmitter'), + related_name='originaltexts' + ) + title = models.CharField(max_length=255, verbose_name=_('title'), null=True, blank=True) + text = models.TextField(verbose_name=_('text')) + translation = models.JSONField(verbose_name=_('translation'), default=list) + share_link = models.CharField(max_length=255, verbose_name=_('share link'), null=True, blank=True) + + def __str__(self): + return f"{self.title} by {self.transmitter.full_name}" \ No newline at end of file diff --git a/apps/hadis/serializers/category.py b/apps/hadis/serializers/category.py index 2d3943e..45ca0b4 100644 --- a/apps/hadis/serializers/category.py +++ b/apps/hadis/serializers/category.py @@ -1,5 +1,6 @@ from rest_framework import serializers from django.utils.translation import gettext_lazy as _ +from django.db.models import Count from ..models import HadisSect, HadisCategory, Hadis , HadisCategory @@ -137,63 +138,83 @@ class HadisCategorySelectSerializer(serializers.ModelSerializer): # children = serializers.SerializerMethodField() children_count = serializers.SerializerMethodField() has_hadis = serializers.SerializerMethodField() + hadis_count= serializers.SerializerMethodField() class Meta: model = HadisCategory - fields = ['id', 'title', 'source_type','slug', 'sect_id', 'sect_type','children_count','has_hadis'] - - # def get_name(self, obj): - # """Get category name based on request language""" - # request = self.context.get('request') - # language_code = getattr(request, 'LANGUAGE_CODE', 'en') - # return obj.get_translation(language_code) if hasattr(obj, 'get_translation') else obj.title + fields = ['id', 'title', 'source_type','slug', 'sect_id', + 'sect_type','children_count','has_hadis','hadis_count'] def get_has_hadis(self, obj): """Check if category can have hadis (no active children) and has hadis""" - children = obj.get_children().filter(sect=obj.sect).order_by('order') - for child in children: - if Hadis.objects.filter(category=child, status=True).exists() : - return True - return False - - # def get_thumbnail(self, obj): - # """Get absolute URL for thumbnail""" - # if hasattr(obj, 'thumbnail') and obj.thumbnail: - # request = self.context.get('request') - # if request: - # return request.build_absolute_uri(obj.thumbnail.url) - # return obj.thumbnail.url - # return None + # Check if category has active children + has_active_children = obj.get_children().filter(sect=obj.sect).exists() + + # If has active children, cannot have hadis + if has_active_children: + return False + + # If no active children, check if has hadis + return Hadis.objects.filter(category=obj, status=True).exists() def get_children_count(self, obj): """Get count of active children categories that have children or hadis""" children = obj.get_children().filter(sect=obj.sect) - # Filter children that have either children or hadis - filtered_children = [] - for child in children: - has_children = child.get_children().filter(sect=obj.sect).exists() - has_hadis = Hadis.objects.filter(category=child, status=True).exists() - if has_children or has_hadis: - filtered_children.append(child) - return len(filtered_children) + return len(children) + def get_hadis_count(self,obj): + return len(Hadis.objects.filter(category=obj)) + + +class HadisCategorySelectSourceSerializer(serializers.ModelSerializer): + """Serializer for HadisCategory Selection Flow""" + sect_id = serializers.IntegerField(source='sect.id', read_only=True) + sect_type = serializers.CharField(source='sect.sect_type', read_only=True) + children_count = serializers.SerializerMethodField() + has_hadis = serializers.SerializerMethodField() + hadis_count = serializers.SerializerMethodField() + + class Meta: + model = HadisCategory + fields = ['id', 'title', 'source_type','slug', 'sect_id', + 'sect_type','children_count','has_hadis','hadis_count'] + + def get_has_hadis(self, obj): + """Check if category can have hadis (no active children) and has hadis""" + # Check if category has active children + has_active_children = obj.get_children().filter(sect=obj.sect).exists() + # If has active children, cannot have hadis + if has_active_children: + return False + # If no active children, check if has hadis + return Hadis.objects.filter(category=obj, status=True).exists() + + def get_children_count(self, obj): + """Get count of active children categories that have children or hadis""" + children = obj.get_children().filter(sect=obj.sect , source_type= obj.source_type) + return len(children) + def get_hadis_count(self,obj): + return len(Hadis.objects.filter(category=obj)) class CategorySerializer(serializers.ModelSerializer): sect_id = serializers.IntegerField(source='sect.id', read_only=True) sect_type = serializers.CharField(source='sect.sect_type', read_only=True) children_count = serializers.SerializerMethodField() + has_hadis =serializers.SerializerMethodField() + hadis_count=serializers.SerializerMethodField() + class Meta: model = HadisCategory - fields = ['id', 'title', 'sect_id', 'sect_type','source_type','description','order','slug','xmind_file', 'children_count'] + fields = ['id', 'title', 'sect_id', 'sect_type','source_type', + 'description','slug', + 'children_count','has_hadis','hadis_count'] def get_children_count(self, obj): """Get count of active children categories that have children or hadis""" children = obj.get_children().filter(sect=obj.sect) - # Filter children that have either children or hadis - filtered_children = [] - for child in children: - has_children = child.get_children().filter(sect=obj.sect).exists() - has_hadis = Hadis.objects.filter(category=child, status=True).exists() - if has_children or has_hadis: - filtered_children.append(child) - return len(filtered_children) + return len(children) + def get_has_hadis(self,obj): + return Hadis.objects.filter(category=obj).exists() + def get_hadis_count(self,obj): + return len(Hadis.objects.filter(category=obj)) + diff --git a/apps/hadis/serializers/hadis.py b/apps/hadis/serializers/hadis.py index 745d20a..08338c4 100644 --- a/apps/hadis/serializers/hadis.py +++ b/apps/hadis/serializers/hadis.py @@ -5,7 +5,7 @@ from urllib3 import fields from ..models import ( Hadis, HadisStatus, HadisTag, HadisTransmitter, HadisReference, ReferenceImage, Transmitters, HadisCollection, - TransmitterOpinion, BookReference, BookReferenceImage, BookAuthor, HadisCorrection + TransmitterOpinion, TransmitterOriginalText, BookReference, BookReferenceImage, BookAuthor, HadisCorrection ) from apps.library.serializers import BookSerializer @@ -148,14 +148,18 @@ class HadisListSerializer(serializers.ModelSerializer): class Meta: model = Hadis - fields = ['id', 'number', 'title', 'text' ,'category', 'translation'] + fields = ['id', 'number', 'title','title_narrator', 'text' , + 'translation','category','share_link'] def get_category(self, obj): """Get category id and title""" if obj.category: return { 'id': obj.category.id, - 'title': obj.category.title + 'title': obj.category.title, + 'slug':obj.category.slug, + 'source_type':obj.category.source_type, + 'sect_type':obj.category.sect.sect_type } return None @@ -189,7 +193,7 @@ class TransmitterSerializer(serializers.ModelSerializer): model = Transmitters fields = [ 'id', 'full_name', 'birth_year_hijri', 'death_year_hijri', - 'description','reliability','madhhab', + "known_as",'nickname','reliability','madhhab', ] class TransmitterOpinionSerializer(serializers.ModelSerializer): """ Serializer for TransmitterOpinions """ @@ -198,6 +202,13 @@ class TransmitterOpinionSerializer(serializers.ModelSerializer): model = TransmitterOpinion fields = '__all__' +class TransmitterOriginalTextSerializer(serializers.ModelSerializer): + """ Serializer for TransmitterOriginalText """ + + class Meta: + model = TransmitterOriginalText + fields = ['id', 'title', 'text', 'translation', 'share_link'] + class HadisTransmitterSerializer(serializers.ModelSerializer): """ Serializer for HadisTransmitters """ @@ -207,17 +218,6 @@ class HadisTransmitterSerializer(serializers.ModelSerializer): class TransmitterDetailSerializer(serializers.ModelSerializer): """ Serializer for Details of Transmitters """ - - opinions = TransmitterOpinionSerializer( - many=True, - read_only=True, - ) - - hadis_transmissions = HadisTransmitterSerializer( - source='hadis', - many=True, - read_only=True, - ) class Meta: model = Transmitters fields = [ @@ -225,7 +225,6 @@ class TransmitterDetailSerializer(serializers.ModelSerializer): 'origin','lived_in','died_in','birth_year_hijri', 'death_year_hijri','age_at_death','reliability', 'madhhab',"in_sahih_muslim","in_sahih_bukhari","description", - "thumbnail",'opinions','hadis_transmissions' ] @@ -367,7 +366,7 @@ class HadisCorrectionSerializer(serializers.ModelSerializer): hadis_translation = serializers.SerializerMethodField() class Meta: model = HadisCorrection - fields = ['id', 'title', 'description', 'hadis_translation', 'created_at', 'updated_at'] + fields = ['id', 'title', 'description', 'hadis_translation','share_link', 'created_at', 'updated_at'] def get_hadis_translation(self, obj): """Get translation based on request language""" @@ -379,11 +378,13 @@ class HadisCorrectionSerializer(serializers.ModelSerializer): class HadisBasicSerializer(serializers.ModelSerializer): """Basic serializer for Hadis with minimal information""" translation = serializers.SerializerMethodField() - + category = serializers.SerializerMethodField() + class Meta: model = Hadis fields = [ - 'id', 'title', 'title_narrator', 'text', 'translation', 'share_link','explanation' + 'id', 'title', 'title_narrator', 'text', + 'translation', 'share_link','explanation','category' ] def get_translation(self, obj): @@ -391,6 +392,17 @@ class HadisBasicSerializer(serializers.ModelSerializer): request = self.context.get('request') language_code = getattr(request, 'LANGUAGE_CODE', 'en') return obj.get_translation(language_code) + def get_category(self, obj): + """Get category id and title""" + if obj.category: + return { + 'id': obj.category.id, + 'title': obj.category.title, + 'slug':obj.category.slug, + 'source_type':obj.category.source_type, + 'sect_type':obj.category.sect.sect_type + } + return None class HadisDetailSerializer(serializers.ModelSerializer): diff --git a/apps/hadis/serializers/reference.py b/apps/hadis/serializers/reference.py index c9ddc4b..656587e 100644 --- a/apps/hadis/serializers/reference.py +++ b/apps/hadis/serializers/reference.py @@ -20,9 +20,13 @@ class BookReferenceSerializer(serializers.ModelSerializer): source = 'bookreference_set' ) volume_count = serializers.SerializerMethodField() + author = serializers.SerializerMethodField() class Meta: model = BookReference - fields = ['id','title','description','rate','image','volume_count'] + fields = ['id','title','rate','author','description','image','volume_count'] + def get_author (self,obj): + author = obj.bookauthor_set + return author.name def get_volume_count(self,obj): request = self.context.get('request') return BookReference.objects.filter(title=obj.title).count() diff --git a/apps/hadis/urls.py b/apps/hadis/urls.py index f28ae83..ef3e105 100644 --- a/apps/hadis/urls.py +++ b/apps/hadis/urls.py @@ -1,7 +1,7 @@ from django.urls import path from .views.category import HadisCategorySectListView, HadisCategoryTreeView, CategoriesView, CategoriesBySectView, HadisCategorySelectBySectView, HadisCategorySelectBySectSourceView , HadisCategoryTreeNormalView from .views.hadis import HadisCollectionListView, HadisListView, HadisBasicView, HadisDetailView, HadisSyncView, HadisTransmittersView, HadisCorrectionsView -from .views.transmitter import TransmitterView ,TransmitterDetailView, TransmitterSyncView +from .views.transmitter import TransmitterView ,TransmitterDetailView, TransmitterSyncView,TransmitterOpinionView, TransmitterOriginalTextView from .views.reference import BookDetailView, BookReferencesView, BookReferenceSyncView from .views.info import HadisInfoView @@ -26,6 +26,8 @@ urlpatterns = [ path('categories/', CategoriesView.as_view(), name='categories'), path('narrators/',TransmitterView.as_view(), name='narrators'), path('narrators/',TransmitterDetailView.as_view(), name='narrator-detail'), + path('narrators//opinions',TransmitterOpinionView.as_view(), name='narrator-opinions'), + path('narrators//original_texts',TransmitterOriginalTextView.as_view(), name='narrator-original-texts'), path('references/',BookReferencesView.as_view(), name='references'), path('references/',BookDetailView.as_view(), name='reference-detail'), ] \ No newline at end of file diff --git a/apps/hadis/views/category.py b/apps/hadis/views/category.py index 8132a39..458a4a6 100644 --- a/apps/hadis/views/category.py +++ b/apps/hadis/views/category.py @@ -4,7 +4,7 @@ from django.shortcuts import get_object_or_404 from utils.pagination import NoPagination from ..models import HadisSect, HadisCategory -from ..serializers import HadisCategorySectListSerializer, HadisCategoryTreeSerializer, CategorySerializer , HadisCategorySelectSerializer +from ..serializers import HadisCategorySectListSerializer, HadisCategoryTreeSerializer, CategorySerializer , HadisCategorySelectSerializer , HadisCategorySelectSourceSerializer from ..docs import ( hadis_sect_list_swagger, hadis_category_tree_swagger, @@ -270,7 +270,7 @@ class HadisCategorySelectBySectSourceView(ListAPIView): Tree view for HadisCategory filtered by sect_type, category slug and source_type. Returns the children categories of the specified category (by slug) within the sect_type, filtered by source_type. """ - serializer_class = HadisCategorySelectSerializer + serializer_class = HadisCategorySelectSourceSerializer @categories_tree_by_sect_source_swagger def get(self, request, *args, **kwargs): diff --git a/apps/hadis/views/transmitter.py b/apps/hadis/views/transmitter.py index a09a10c..1c2714a 100644 --- a/apps/hadis/views/transmitter.py +++ b/apps/hadis/views/transmitter.py @@ -1,9 +1,11 @@ from django.contrib.admin.utils import lookup_field from rest_framework.generics import ListAPIView , RetrieveAPIView from rest_framework.response import Response -from ..models import Transmitters , TransmitterOpinion -from ..serializers import TransmitterSerializer , TransmitterDetailSerializer, TransmitterSyncSerializer -from ..docs import transmitter_list_swagger, transmitter_detail_swagger, transmitter_sync_swagger + + +from ..models import Transmitters , TransmitterOpinion, TransmitterOriginalText +from ..serializers import TransmitterSerializer , TransmitterDetailSerializer, TransmitterSyncSerializer,TransmitterOpinionSerializer, TransmitterOriginalTextSerializer +from ..docs import transmitter_list_swagger, transmitter_detail_swagger, transmitter_sync_swagger, transmitter_opinion_swagger, transmitter_original_text_swagger from utils.pagination import NoPagination class TransmitterView(ListAPIView): @@ -54,6 +56,29 @@ class TransmitterDetailView(RetrieveAPIView): input = self.kwargs['transmitters_id'] return Transmitters.objects.filter(id=input) +class TransmitterOpinionView(ListAPIView): + serializer_class = TransmitterOpinionSerializer + + @transmitter_opinion_swagger + def get(self, request, *args, **kwargs): + return self.list(request, *args, **kwargs) + + def get_queryset(self): + transmitter_id = self.kwargs['transmitters_id'] + return TransmitterOpinion.objects.filter(transmitter_id=transmitter_id) + + +class TransmitterOriginalTextView(ListAPIView): + serializer_class = TransmitterOriginalTextSerializer + + @transmitter_original_text_swagger + def get(self, request, *args, **kwargs): + return self.list(request, *args, **kwargs) + + def get_queryset(self): + transmitter_id = self.kwargs['transmitters_id'] + return TransmitterOriginalText.objects.filter(transmitter_id=transmitter_id) + class TransmitterSyncView(ListAPIView): """