Browse Source

category endpoints compeleted

master
Mohsen Taba 5 months ago
parent
commit
89d48ecd07
  1. 528
      apps/hadis/docs.py
  2. 17
      apps/hadis/migrations/0006_hadiscategory_slug.py
  3. 29
      apps/hadis/migrations/0007_auto_20251211_1313.py
  4. 29
      apps/hadis/migrations/0007_auto_20251211_1324.py
  5. 17
      apps/hadis/migrations/0008_alter_hadiscategory_slug.py
  6. 17
      apps/hadis/migrations/0009_alter_hadiscategory_slug.py
  7. 12
      apps/hadis/migrations/0010_merge_20251211_1555.py
  8. 17
      apps/hadis/migrations/0011_hadis_a.py
  9. 16
      apps/hadis/migrations/0012_remove_hadis_title_narrator.py
  10. 19
      apps/hadis/migrations/0013_hadis_title_narrator.py
  11. 13
      apps/hadis/models/category.py
  12. 1
      apps/hadis/models/hadis.py
  13. 2
      apps/hadis/models/reference.py
  14. 61
      apps/hadis/serializers/category.py
  15. 2
      apps/hadis/serializers/hadis.py
  16. 6
      apps/hadis/urls.py
  17. 115
      apps/hadis/views/category.py
  18. 17
      apps/hadis/views/reference.py
  19. 39
      apps/hadis/views/transmitter.py
  20. 535
      docs/categories_api_check.MD

528
apps/hadis/docs.py

@ -80,6 +80,7 @@ hadis_category_tree_swagger = swagger_auto_schema(
"order": 1,
"xmind_file": "http://example.com/media/xmind/tafsir.xmind",
"has_xmind_file": True,
"children_count": 2,
"children": [
{
"id": 2,
@ -89,6 +90,7 @@ hadis_category_tree_swagger = swagger_auto_schema(
"order": 1,
"xmind_file": None,
"has_xmind_file": False,
"children_count": 0,
"children": []
},
{
@ -99,6 +101,7 @@ hadis_category_tree_swagger = swagger_auto_schema(
"order": 2,
"xmind_file": "http://example.com/media/xmind/baqarah.xmind",
"has_xmind_file": True,
"children_count": 0,
"children": []
}
]
@ -113,6 +116,7 @@ hadis_category_tree_swagger = swagger_auto_schema(
"order": 1,
"xmind_file": "http://example.com/media/xmind/bukhari.xmind",
"has_xmind_file": True,
"children_count": 2,
"children": [
{
"id": 5,
@ -122,6 +126,7 @@ hadis_category_tree_swagger = swagger_auto_schema(
"order": 1,
"xmind_file": None,
"has_xmind_file": False,
"children_count": 0,
"children": []
},
{
@ -132,6 +137,7 @@ hadis_category_tree_swagger = swagger_auto_schema(
"order": 2,
"xmind_file": "http://example.com/media/xmind/prayer.xmind",
"has_xmind_file": True,
"children_count": 0,
"children": []
}
]
@ -339,3 +345,525 @@ hadis_detail_swagger = swagger_auto_schema(
404: openapi.Response(description="Hadis not found")
}
)
# Swagger documentation for TransmitterView
transmitter_list_swagger = swagger_auto_schema(
operation_description="Get list of transmitters (narrators) with optional filtering by status, madhhab, and generation",
operation_summary="List Transmitters",
tags=['Hadis'],
manual_parameters=[
openapi.Parameter(
'status',
openapi.IN_QUERY,
description='Filter by reliability status (very_reliable, reliable, acceptable, weak, very_weak, unknown)',
type=openapi.TYPE_STRING,
required=False
),
openapi.Parameter(
'madhhab',
openapi.IN_QUERY,
description='Filter by madhhab/school (shia, sunni, hanafi, maliki, shafii, hanbali, other, unknown)',
type=openapi.TYPE_STRING,
required=False
),
openapi.Parameter(
'generation',
openapi.IN_QUERY,
description='Filter by generation (1-10 representing narrator layers/classes)',
type=openapi.TYPE_INTEGER,
required=False
),
],
responses={
status.HTTP_200_OK: openapi.Response(
description="List of transmitters with optional filtering applied",
examples={
"application/json": [
{
"id": 1,
"full_name": "Abu Daud Sulaiman ibn al-Ash'ath al-Azdi al-Sijistani",
"birth_year_hijri": 202,
"death_year_hijri": 275,
"description": "Imam Abu Daud, compiler of Sunan Abu Daud, one of the six major hadith collections"
},
{
"id": 2,
"full_name": "Muhammad ibn Isma'il al-Bukhari",
"birth_year_hijri": 194,
"death_year_hijri": 256,
"description": "Imam Bukhari, compiler of Sahih al-Bukhari, the most authentic hadith collection"
}
]
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# Swagger documentation for TransmitterDetailView
transmitter_detail_swagger = swagger_auto_schema(
operation_description="Get detailed information about a specific transmitter including their scholarly opinions and hadith transmissions",
operation_summary="Get Transmitter Details",
tags=['Hadis'],
manual_parameters=[
openapi.Parameter(
'transmitters_id',
openapi.IN_PATH,
description="ID of the transmitter",
type=openapi.TYPE_INTEGER,
required=True
)
],
responses={
status.HTTP_200_OK: openapi.Response(
description="Detailed transmitter information with nested opinions and transmissions",
examples={
"application/json": {
"id": 1,
"full_name": "Abu Daud Sulaiman ibn al-Ash'ath al-Azdi al-Sijistani",
"kunya": "Abu Daud",
"known_as": "Imam Abu Daud",
"nickname": "Al-Sijistani",
"origin": "Sijistan (modern Sistan)",
"lived_in": "Basra, Baghdad",
"died_in": "Basra",
"birth_year_hijri": 202,
"death_year_hijri": 275,
"age_at_death": 73,
"reliability": "very_reliable",
"madhhab": "sunni",
"in_sahih_bukhari": False,
"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"
}
]
}
}
),
status.HTTP_404_NOT_FOUND: openapi.Response(
description="Transmitter not found"
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# 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_summary="List Book References",
tags=['Hadis'],
responses={
status.HTTP_200_OK: openapi.Response(
description="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",
"rate": 5.0,
"image": [
{
"id": 1,
"image": "http://example.com/media/books/bukhari_cover.jpg",
"order": 1,
"description": "Front cover of Sahih al-Bukhari",
"created_at": "2024-01-01T00:00:00Z"
}
],
"volume_count": 9
},
{
"id": 2,
"title": "Sahih Muslim",
"description": "The second most authentic collection of hadith compiled by Imam Muslim",
"rate": 4.9,
"image": [],
"volume_count": 7
}
]
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# Swagger documentation for BookAuthorView
book_authors_list_swagger = swagger_auto_schema(
operation_description="Get list of all book authors who have contributed to hadith literature",
operation_summary="List Book Authors",
tags=['Hadis'],
responses={
status.HTTP_200_OK: openapi.Response(
description="List of all book authors",
examples={
"application/json": [
{
"id": 1,
"name": "Muhammad ibn Isma'il al-Bukhari",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
},
{
"id": 2,
"name": "Muslim ibn al-Hajjaj al-Qushayri",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# 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_summary="Get Book Reference Details",
tags=['Hadis'],
manual_parameters=[
openapi.Parameter(
'bookreference_id',
openapi.IN_PATH,
description="ID of the book reference",
type=openapi.TYPE_INTEGER,
required=True
)
],
responses={
status.HTTP_200_OK: openapi.Response(
description="Detailed book reference information",
examples={
"application/json": {
"id": 1,
"title": "Sahih al-Bukhari",
"description": "The most authentic collection of hadith compiled by Imam Bukhari",
"language": "Arabic",
"isbn": "978-1234567890",
"volume": "9 volumes",
"year_of_publication": "846",
"number_page": 4200,
"rate": 5.0,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"author": [
{
"id": 1,
"name": "Muhammad ibn Isma'il al-Bukhari",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
],
"image": [
{
"id": 1,
"image": "http://example.com/media/books/bukhari_cover.jpg",
"order": 1,
"description": "Front cover of Sahih al-Bukhari",
"created_at": "2024-01-01T00:00:00Z"
}
],
"hadis": [
{
"id": 1,
"number": 1,
"title": "The first hadith about faith",
"category": {
"id": 1,
"title": "Book of Faith"
},
"translation": "Actions are by intentions"
}
]
}
}
),
status.HTTP_404_NOT_FOUND: openapi.Response(
description="Book reference not found"
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# Swagger documentation for CategoriesView
categories_list_swagger = swagger_auto_schema(
operation_description="Get list of all hadith categories with their associated sect information",
operation_summary="List All Categories",
tags=['Hadis'],
responses={
status.HTTP_200_OK: openapi.Response(
description="List of all hadith categories",
examples={
"application/json": [
{
"id": 1,
"title": "Book of Faith",
"sect_id": 1,
"sect_type": "sunni",
"source_type": "hadith",
"description": "Hadiths related to Islamic faith and beliefs",
"order": 1,
"slug": "book-of-faith",
"xmind_file": "http://example.com/media/xmind/faith.xmind",
"children_count": 3
},
{
"id": 2,
"title": "Book of Prayer",
"sect_id": 1,
"sect_type": "sunni",
"source_type": "hadith",
"description": "Hadiths about salah (prayer) and related rulings",
"order": 2,
"slug": "book-of-prayer",
"xmind_file": None,
"children_count": 0
}
]
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# 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_summary="List Categories by Sect",
tags=['Hadis'],
manual_parameters=[
openapi.Parameter(
'sect_type',
openapi.IN_PATH,
description="Type of Islamic sect (shia or sunni)",
type=openapi.TYPE_STRING,
enum=['shia', 'sunni'],
required=True
)
],
responses={
status.HTTP_200_OK: openapi.Response(
description="List of hadith categories filtered by sect type",
examples={
"application/json": [
{
"id": 1,
"title": "Book of Faith",
"sect_id": 1,
"sect_type": "sunni",
"source_type": "hadith",
"description": "Hadiths related to Islamic faith and beliefs",
"order": 1,
"slug": "book-of-faith",
"xmind_file": "http://example.com/media/xmind/faith.xmind",
"children_count": 3
},
{
"id": 2,
"title": "Book of Prayer",
"sect_id": 1,
"sect_type": "sunni",
"source_type": "hadith",
"description": "Hadiths about salah (prayer) and related rulings",
"order": 2,
"slug": "book-of-prayer",
"xmind_file": None,
"children_count": 0
}
]
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# 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_summary="Get Category Children by Sect and Slug",
operation_id="getCategoryChildrenBySectAndSlug",
tags=['Hadis'],
manual_parameters=[
openapi.Parameter(
'sect_type',
openapi.IN_PATH,
description="Type of Islamic sect (shia or sunni)",
type=openapi.TYPE_STRING,
enum=['shia', 'sunni'],
required=True
),
openapi.Parameter(
'slug',
openapi.IN_PATH,
description="URL slug of the parent category",
type=openapi.TYPE_STRING,
required=True
)
],
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",
examples={
"application/json": [
{
"id": 330,
"title": "Толкование суры Аль-Фатиха",
"source_type": "quran",
"slug": "-1",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0
},
{
"id": 331,
"title": "Толкование суры Аль-Бакара",
"source_type": "quran",
"slug": "-19",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0
},
{
"id": 332,
"title": "Толкование суры Аль Имран",
"source_type": "quran",
"slug": "-33",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0
}
]
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# 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_summary="Get Category Children by Sect, Slug and Source",
operation_id="getCategoryChildrenBySectSlugAndSource",
tags=['Hadis'],
manual_parameters=[
openapi.Parameter(
'sect_type',
openapi.IN_PATH,
description="Type of Islamic sect (shia or sunni)",
type=openapi.TYPE_STRING,
enum=['shia', 'sunni'],
required=True
),
openapi.Parameter(
'slug',
openapi.IN_PATH,
description="URL slug of the parent category",
type=openapi.TYPE_STRING,
required=True
),
openapi.Parameter(
'source_type',
openapi.IN_PATH,
description="Type of source material (quran, hadith, history, fatwa, quote)",
type=openapi.TYPE_STRING,
enum=['quran', 'hadith', 'history', 'fatwa', 'quote'],
required=True
)
],
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",
examples={
"application/json": [
{
"id": 330,
"title": "Толкование суры Аль-Фатиха",
"source_type": "quran",
"slug": "-1",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0,
"has_hadis": False
},
{
"id": 331,
"title": "Толкование суры Аль-Бакара",
"source_type": "quran",
"slug": "-19",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0,
"has_hadis": False
},
{
"id": 332,
"title": "Толкование суры Аль Имран",
"source_type": "quran",
"slug": "-33",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0,
"has_hadis": False
}
]
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)

17
apps/hadis/migrations/0006_hadiscategory_slug.py

@ -0,0 +1,17 @@
# Generated by Django 5.2.9 on 2025-12-11 13:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0005_auto_20251209_1620"),
]
operations = [
migrations.AddField(
model_name="hadiscategory",
name="slug",
field=models.SlugField(blank=True, max_length=255, null=True),
),
]

29
apps/hadis/migrations/0007_auto_20251211_1313.py

@ -0,0 +1,29 @@
# Generated by Django 5.2.9 on 2025-12-11 13:13
from django.db import migrations
from django.utils.text import slugify
def gen_slugs(apps, schema_editor):
MyModel = apps.get_model('hadis', 'HadisCategory') # Replace with your app/model name
for row in MyModel.objects.all():
# 1. Basic slugify
base_slug = slugify(row.title) # Assuming you slugify the 'name' field
slug = base_slug
n = 1
# 2. Ensure uniqueness (if two rows have the same name)
while MyModel.objects.filter(slug=slug).exists():
slug = f"{base_slug}-{n}"
n += 1
row.slug = slug
row.save()
class Migration(migrations.Migration):
dependencies = [
("hadis", "0005_auto_20251209_1620"),
]
operations = [
migrations.RunPython(gen_slugs, reverse_code=migrations.RunPython.noop),
]

29
apps/hadis/migrations/0007_auto_20251211_1324.py

@ -0,0 +1,29 @@
from django.db import migrations
from django.utils.text import slugify
def gen_slugs(apps, schema_editor):
MyModel = apps.get_model('hadis', 'HadisCategory') # Replace with your app/model name
for row in MyModel.objects.all():
# 1. Basic slugify
base_slug = slugify(row.title) # Assuming you slugify the 'name' field
slug = base_slug
n = 1
# 2. Ensure uniqueness (if two rows have the same name)
while MyModel.objects.filter(slug=slug).exists():
slug = f"{base_slug}-{n}"
n += 1
row.slug = slug
row.save()
class Migration(migrations.Migration):
dependencies = [
('hadis', '0006_hadiscategory_slug'),
]
operations = [
# Call the function
migrations.RunPython(gen_slugs, reverse_code=migrations.RunPython.noop),
]

17
apps/hadis/migrations/0008_alter_hadiscategory_slug.py

@ -0,0 +1,17 @@
# Generated by Django 5.2.9 on 2025-12-11 13:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0007_auto_20251211_1324"),
]
operations = [
migrations.AlterField(
model_name="hadiscategory",
name="slug",
field=models.SlugField(blank=True, max_length=255, null=True, unique=True),
),
]

17
apps/hadis/migrations/0009_alter_hadiscategory_slug.py

@ -0,0 +1,17 @@
# Generated by Django 5.2.9 on 2025-12-11 13:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0008_alter_hadiscategory_slug"),
]
operations = [
migrations.AlterField(
model_name="hadiscategory",
name="slug",
field=models.SlugField(blank=True, max_length=255, null=True),
),
]

12
apps/hadis/migrations/0010_merge_20251211_1555.py

@ -0,0 +1,12 @@
# Generated by Django 5.2.9 on 2025-12-11 15:55
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("hadis", "0007_auto_20251211_1313"),
("hadis", "0009_alter_hadiscategory_slug"),
]
operations = []

17
apps/hadis/migrations/0011_hadis_a.py

@ -0,0 +1,17 @@
# Generated by Django 5.2.9 on 2025-12-11 16:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0010_merge_20251211_1555"),
]
operations = [
migrations.AddField(
model_name="hadis",
name="a",
field=models.IntegerField(blank=True, null=True),
),
]

16
apps/hadis/migrations/0012_remove_hadis_title_narrator.py

@ -0,0 +1,16 @@
# Generated by Django 5.2.9 on 2025-12-11 16:13
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("hadis", "0011_hadis_a"),
]
operations = [
migrations.RemoveField(
model_name="hadis",
name="title_narrator",
),
]

19
apps/hadis/migrations/0013_hadis_title_narrator.py

@ -0,0 +1,19 @@
# Generated by Django 5.2.9 on 2025-12-11 16:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0012_remove_hadis_title_narrator"),
]
operations = [
migrations.AddField(
model_name="hadis",
name="title_narrator",
field=models.CharField(
blank=True, max_length=255, null=True, verbose_name="title narrator"
),
),
]

13
apps/hadis/models/category.py

@ -2,6 +2,7 @@ from django.db import models
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError
from mptt.models import MPTTModel, TreeForeignKey
from django.utils.text import slugify
class HadisSect(models.Model):
@ -40,11 +41,21 @@ class HadisCategory(MPTTModel):
description = models.TextField(verbose_name=_('Description'), null=True, blank=True)
order = models.IntegerField(default=0, verbose_name=_('order'))
xmind_file = models.FileField(upload_to='hadis/xmind_files/', verbose_name=_('xmind file'), null=True, blank=True)
slug = None
slug = models.SlugField(max_length=255, null=True, blank=True)
content_type = None
language = None
language_id = None
def save(self, *args, **kwargs):
if not self.slug:
base_slug = slugify(self.title, allow_unicode=True)
slug = base_slug
while HadisCategory.objects.filter(slug=slug).exclude(pk=self.pk).exists():
slug = f"{base_slug}"
self.slug = slug
super().save(*args, **kwargs)
class Meta:
verbose_name = _('Hadis Category')

1
apps/hadis/models/hadis.py

@ -100,6 +100,7 @@ class Hadis(models.Model):
number = models.PositiveIntegerField(verbose_name=_('number'), default=1)
title_narrator = models.CharField(max_length=255, verbose_name=_('title narrator'), null=True, blank=True)
title = models.CharField(max_length=255, verbose_name=_('title'), null=True, blank=True)
a =models.IntegerField(blank=True ,null=True)
text = models.TextField(verbose_name=_('text'))
translation = models.JSONField(verbose_name=_('translation'), default=list)

2
apps/hadis/models/reference.py

@ -1,5 +1,6 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils.text import slugify
class BookReference(models.Model):
@ -14,6 +15,7 @@ class BookReference(models.Model):
volume = models.CharField(max_length=100, verbose_name=_('volume'), blank=True, null=True)
year_of_publication = models.CharField(max_length=50, verbose_name=_('year of publication'), blank=True, null=True)
number_page = models.PositiveIntegerField(verbose_name=_('number of pages'), blank=True, null=True)
# publisher = models.TextField(verbose_name=_('publisher'),blank=True,null=True)
rate = models.DecimalField(
max_digits=3,
decimal_places=2,

61
apps/hadis/serializers/category.py

@ -130,11 +130,70 @@ class HadisCategoryTreeSerializer(serializers.ModelSerializer):
'children': [] if not filtered_children else [self.to_dict(i) for i in filtered_children],
}
class HadisCategorySelectSerializer(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 = serializers.SerializerMethodField()
children_count = serializers.SerializerMethodField()
has_hadis = 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
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
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)
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()
class Meta:
model = HadisCategory
fields = ['id', 'title', 'sect_id', 'sect_type','source_type','description','order','slug','xmind_file']
fields = ['id', 'title', 'sect_id', 'sect_type','source_type','description','order','slug','xmind_file', 'children_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)

2
apps/hadis/serializers/hadis.py

@ -115,7 +115,7 @@ class TransmitterSerializer(serializers.ModelSerializer):
model = Transmitters
fields = [
'id', 'full_name', 'birth_year_hijri', 'death_year_hijri',
'description'
'description','reliability','madhhab',
]
class TransmitterOpinionSerializer(serializers.ModelSerializer):
""" Serializer for TransmitterOpinions """

6
apps/hadis/urls.py

@ -1,5 +1,5 @@
from django.urls import path
from .views.category import HadisCategorySectListView, HadisCategoryTreeView,CategoriesView
from .views.category import HadisCategorySectListView, HadisCategoryTreeView, CategoriesView, CategoriesBySectView, HadisCategorySelectBySectView, HadisCategorySelectBySectSourceView , HadisCategoryTreeNormalView
from .views.hadis import HadisCollectionListView, HadisListView, HadisDetailView, HadisSyncView
from .views.transmitter import TransmitterView ,TransmitterDetailView
from .views.reference import BookDetailView, BookReferencesView
@ -10,10 +10,14 @@ urlpatterns = [
path('collections/', HadisCollectionListView.as_view(), name='hadis-collection-list'),
path('sync/sects/', HadisCategorySectListView.as_view(), name='hadis-sect-list'),
path('sync/categories/tree/', HadisCategoryTreeView.as_view(), name='hadis-category-tree'),
path('categories/tree/', HadisCategoryTreeNormalView.as_view(), name='hadis-category-tree-normal'),
path('sync/hadis/', HadisSyncView.as_view(), name='hadis-sync'),
path('info/', HadisInfoView.as_view(), name='hadis-info'),
path('category/<int:category_id>/', HadisListView.as_view(), name='hadis-list'),
path('<int:hadis_id>/', HadisDetailView.as_view(), name='hadis-detail'),
path('categories/<str:sect_type>/<str:slug>/<str:source_type>/', HadisCategorySelectBySectSourceView.as_view(), name='categories-tree-by-sect-source'),
path('categories/<str:sect_type>/<str:slug>/', HadisCategorySelectBySectView.as_view(), name='categories-tree-by-sect'),
path('categories/<str:sect_type>/', CategoriesBySectView.as_view(), name='categories-by-sect'),
path('categories/', CategoriesView.as_view(), name='categories'),
path('narrators/',TransmitterView.as_view(), name='narrators'),
path('narrators/<int:transmitters_id>',TransmitterDetailView.as_view(), name='narrator-detail'),

115
apps/hadis/views/category.py

@ -4,8 +4,15 @@ from django.shortcuts import get_object_or_404
from utils.pagination import NoPagination
from ..models import HadisSect, HadisCategory
from ..serializers import HadisCategorySectListSerializer, HadisCategoryTreeSerializer, CategorySerializer
from ..docs import hadis_sect_list_swagger, hadis_category_tree_swagger
from ..serializers import HadisCategorySectListSerializer, HadisCategoryTreeSerializer, CategorySerializer , HadisCategorySelectSerializer
from ..docs import (
hadis_sect_list_swagger,
hadis_category_tree_swagger,
categories_list_swagger,
categories_by_sect_swagger,
categories_tree_by_sect_swagger,
categories_tree_by_sect_source_swagger
)
class HadisCategorySectListView(ListAPIView):
@ -127,16 +134,118 @@ class HadisCategoryTreeView(ListAPIView):
return Response(response_data)
class HadisCategoryTreeNormalView(ListAPIView):
"""
Normal (paginated) tree view for HadisCategory.
Unlike the sync view, this simply returns the root categories (filtered to active sects)
with their nested children, and uses the project's default pagination.
"""
serializer_class = HadisCategoryTreeSerializer
@hadis_category_tree_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def get_queryset(self):
return HadisCategory.objects.filter(
parent__isnull=True,
sect__is_active=True
).order_by('sect__order', 'order')
class HadisCategorySelectBySectView(ListAPIView):
"""
Tree view for HadisCategory filtered by sect_type and category slug.
Returns the children categories of the specified category (by slug) within the sect_type.
"""
serializer_class = HadisCategorySelectSerializer
@categories_tree_by_sect_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def get_queryset(self):
sect_type = self.kwargs.get('sect_type')
slug = self.kwargs.get('slug')
# Find the parent category by slug and sect_type
try:
parent_category = HadisCategory.objects.get(
slug=slug,
sect__sect_type=sect_type,
sect__is_active=True
)
except HadisCategory.DoesNotExist:
return HadisCategory.objects.none()
# Return children of this category, filtered as before
return HadisCategory.objects.filter(
parent=parent_category,
sect__sect_type=sect_type,
sect__is_active=True
).order_by('order')
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
@categories_tree_by_sect_source_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def get_queryset(self):
sect_type = self.kwargs.get('sect_type')
slug = self.kwargs.get('slug')
source_type = self.kwargs.get('source_type')
# Find the parent category by slug and sect_type
try:
parent_category = HadisCategory.objects.get(
slug=slug,
sect__sect_type=sect_type,
sect__is_active=True
)
except HadisCategory.DoesNotExist:
return HadisCategory.objects.none()
# Return children of this category, filtered by source_type
return HadisCategory.objects.filter(
parent=parent_category,
sect__sect_type=sect_type,
sect__is_active=True,
source_type=source_type
).order_by('order')
class CategoriesView(ListAPIView):
"""
API view to list all HadisCategories
"""
queryset = HadisCategory.objects.all()
serializer_class = CategorySerializer
pagination_class = NoPagination
@categories_list_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
class CategoriesBySectView(ListAPIView):
"""
API view to list HadisCategories filtered by sect_type
"""
serializer_class = CategorySerializer
def get_queryset(self):
sect_type = self.kwargs.get('sect_type')
return HadisCategory.objects.filter(sect__sect_type=sect_type)
@categories_by_sect_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)

17
apps/hadis/views/reference.py

@ -1,6 +1,7 @@
from rest_framework.generics import ListAPIView, RetrieveAPIView
from ..models import BookReference , BookAuthor , BookReferenceImage
from ..serializers.reference import BookAuthorSerializer, BookDetailSerializer , BookReferenceSerializer
from ..docs import book_references_list_swagger, book_authors_list_swagger, book_detail_swagger
from utils.pagination import NoPagination
@ -8,21 +9,31 @@ from utils.pagination import NoPagination
class BookReferencesView(ListAPIView):
queryset = BookReference.objects.all()
serializer_class = BookReferenceSerializer
pagination_class = NoPagination
@book_references_list_swagger
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
class BookAuthorView(ListAPIView):
queryset = BookAuthor.objects.all()
serializer_class = BookAuthorSerializer
pagination_class = NoPagination
@book_authors_list_swagger
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
class BookDetailView(RetrieveAPIView):
serializer_class = BookDetailSerializer
lookup_field = 'id'
lookup_url_kwarg = 'bookreference_id'
@book_detail_swagger
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
return BookReference.objects.all().prefetch_related(
return BookReference.objects.filter(id = self.kwargs['bookreference_id']).prefetch_related(
'bookauthor_set__name',
'bookreferenceimage_set__image',
)

39
apps/hadis/views/transmitter.py

@ -2,16 +2,53 @@ from django.contrib.admin.utils import lookup_field
from rest_framework.generics import ListAPIView , RetrieveAPIView
from ..models import Transmitters , TransmitterOpinion
from ..serializers import TransmitterSerializer , TransmitterDetailSerializer
from ..docs import transmitter_list_swagger, transmitter_detail_swagger
from utils.pagination import NoPagination
class TransmitterView(ListAPIView):
queryset = Transmitters.objects.all()
serializer_class = TransmitterSerializer
pagination_class = NoPagination
@transmitter_list_swagger
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
queryset = Transmitters.objects.all()
# Filter by status (reliability)
status_filter = self.request.query_params.get('status', None)
if status_filter:
queryset = queryset.filter(reliability=status_filter)
# Filter by madhhab
madhhab_filter = self.request.query_params.get('madhhab', None)
if madhhab_filter:
queryset = queryset.filter(madhhab=madhhab_filter)
# Filter by generation (narrator layer)
# generation_filter = self.request.query_params.get('generation', None)
# if generation_filter:
# try:
# generation_num = int(generation_filter)
# # Filter transmitters who have hadis transmissions in the specified generation/layer
# queryset = queryset.filter(
# hadi=generation_num
# ).distinct()
# except (ValueError, TypeError):
# pass # Invalid generation number, ignore filter
return queryset
class TransmitterDetailView(RetrieveAPIView):
serializer_class = TransmitterDetailSerializer
lookup_field = 'id'
lookup_url_kwarg = 'transmitters_id'
@transmitter_detail_swagger
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
def get_queryset(self):
input = self.kwargs['transmitters_id']
return Transmitters.objects.filter(id=input)

535
docs/categories_api_check.MD

@ -0,0 +1,535 @@
# 📋 Categories API Response Examples
## 1. GET `/api/hadis/categories/`
**Description**: Returns all categories with pagination (limited to 16 items per page).
**Response Structure:**
```json
{
"count": 56,
"next": "http://127.0.0.1:8000/api/hadis/categories/?limit=16&offset=16",
"previous": null,
"results": [
{
"id": 324,
"title": "Толкование Корана",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 3
},
{
"id": 330,
"title": "Толкование суры Аль-Фатиха",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 331,
"title": "Толкование суры Аль-Бакара",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 2,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 332,
"title": "Толкование суры Аль Имран",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 3,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 325,
"title": "Аяты постановлений",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 2,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_325_%D0%90%D1%8F%D1%82%D1%8B_%D0%BF%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9.xmind",
"children_count": 3
},
{
"id": 333,
"title": "Аяты о молитве",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 334,
"title": "Аяты о посте",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 2,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 335,
"title": "Аяты о закяте",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 3,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 326,
"title": "Коранические истории",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 3,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_326_%D0%9A%D0%BE%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5_%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8.xmind",
"children_count": 0
},
{
"id": 336,
"title": "Истории пророков",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 337,
"title": "Истории праведников",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 2,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 327,
"title": "Достоинства сур",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 4,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_327_%D0%94%D0%BE%D1%81%D1%82%D0%BE%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B0_%D1%81%D1%83%D1%80.xmind",
"children_count": 0
},
{
"id": 328,
"title": "Чудеса Корана",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 5,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_328_%D0%A7%D1%83%D0%B4%D0%B5%D1%81%D0%B0_%D0%9A%D0%BE%D1%80%D0%B0%D0%BD%D0%B0.xmind",
"children_count": 0
},
{
"id": 329,
"title": "Коранические науки",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 6,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 338,
"title": "Книга очищения",
"sect_id": 20,
"sect_type": "shia",
"source_type": "hadith",
"description": null,
"order": 1,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_338_%D0%9A%D0%BD%D0%B8%D0%B3%D0%B0_%D0%BE%D1%87%D0%B8%D1%89%D0%B5%D0%BD%D0%B8%D1%8F.xmind",
"children_count": 0
},
{
"id": 344,
"title": "Омовение",
"sect_id": 20,
"sect_type": "shia",
"source_type": "hadith",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 0
}
]
}
```
## 2. GET `/api/hadis/categories/{sect_type}/`
**Description**: Returns categories filtered by sect type (shia or sunni).
**Parameters:**
- `sect_type`: Islamic sect type (`shia` or `sunni`)
**Example URL:** `GET /api/hadis/categories/shia/`
**Response Structure:**
```json
{
"count": 28,
"next": "http://127.0.0.1:8000/api/hadis/categories/shia/?limit=16&offset=16",
"previous": null,
"results": [
{
"id": 324,
"title": "Толкование Корана",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 3
},
{
"id": 330,
"title": "Толкование суры Аль-Фатиха",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 331,
"title": "Толкование суры Аль-Бакара",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 2,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 332,
"title": "Толкование суры Аль Имран",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 3,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 325,
"title": "Аяты постановлений",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 2,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_325_%D0%90%D1%8F%D1%82%D1%8B_%D0%BF%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9.xmind",
"children_count": 3
},
{
"id": 333,
"title": "Аяты о молитве",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 334,
"title": "Аяты о посте",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 2,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 335,
"title": "Аяты о закяте",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 3,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 326,
"title": "Коранические истории",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 3,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_326_%D0%9A%D0%BE%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5_%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8.xmind",
"children_count": 0
},
{
"id": 336,
"title": "Истории пророков",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 337,
"title": "Истории праведников",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 2,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 327,
"title": "Достоинства сур",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 4,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_327_%D0%94%D0%BE%D1%81%D1%82%D0%BE%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B0_%D1%81%D1%83%D1%80.xmind",
"children_count": 0
},
{
"id": 328,
"title": "Чудеса Корана",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 5,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_328_%D0%A7%D1%83%D0%B4%D0%B5%D1%81%D0%B0_%D0%9A%D0%BE%D1%80%D0%B0%D0%BD%D0%B0.xmind",
"children_count": 0
},
{
"id": 329,
"title": "Коранические науки",
"sect_id": 20,
"sect_type": "shia",
"source_type": "quran",
"description": null,
"order": 6,
"slug": null,
"xmind_file": null,
"children_count": 0
},
{
"id": 338,
"title": "Книга очищения",
"sect_id": 20,
"sect_type": "shia",
"source_type": "hadith",
"description": null,
"order": 1,
"slug": null,
"xmind_file": "http://127.0.0.1:8000/media/hadis/xmind_files/category_338_%D0%9A%D0%BD%D0%B8%D0%B3%D0%B0_%D0%BE%D1%87%D0%B8%D1%89%D0%B5%D0%BD%D0%B8%D1%8F.xmind",
"children_count": 0
},
{
"id": 344,
"title": "Омовение",
"sect_id": 20,
"sect_type": "shia",
"source_type": "hadith",
"description": null,
"order": 1,
"slug": null,
"xmind_file": null,
"children_count": 0
}
]
}
```
## 3. GET `/api/hadis/categories/{sect_type}/{slug}/`
**Description**: Returns child categories of a specific category (by slug) within the sect type.
**Parameters:**
- `sect_type`: Islamic sect type (`shia` or `sunni`)
- `slug`: URL slug of the parent category
**Example URL:** `GET /api/hadis/categories/shia/some-category-slug/`
**Response Structure:**
```json
{
"count": 3,
"next": null,
"previous": null,
"results": [
{
"id": 330,
"title": "Толкование суры Аль-Фатиха",
"source_type": "quran",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0
},
{
"id": 331,
"title": "Толкование суры Аль-Бакара",
"source_type": "quran",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0
},
{
"id": 332,
"title": "Толкование суры Аль Имран",
"source_type": "quran",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0
}
]
}
```
## 4. GET `/api/hadis/categories/{sect_type}/{slug}/{source_type}/`
**Description**: Returns child categories of a specific category (by slug) within the sect type, filtered by source type.
**Parameters:**
- `sect_type`: Islamic sect type (`shia` or `sunni`)
- `slug`: URL slug of the parent category
- `source_type`: Source material type (`quran`, `hadith`, `history`, `fatwa`, `quote`)
**Example URL:** `GET /api/hadis/categories/shia/some-category-slug/quran/`
**Response Structure:**
```json
{
"count": 3,
"next": null,
"previous": null,
"results": [
{
"id": 330,
"title": "Толкование суры Аль-Фатиха",
"source_type": "quran",
"slug": "-1",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0,
"has_hadis": false
},
{
"id": 331,
"title": "Толкование суры Аль-Бакара",
"source_type": "quran",
"slug": "-19",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0,
"has_hadis": false
},
{
"id": 332,
"title": "Толкование суры Аль Имран",
"source_type": "quran",
"slug": "-33",
"sect_id": 20,
"sect_type": "shia",
"children_count": 0,
"has_hadis": false
}
]
}
```
---
## 🔍 Field Descriptions
- **`id`**: Unique identifier for the category
- **`title`**: Category name in Russian
- **`sect_id`**: ID of the Islamic sect
- **`sect_type`**: Type of Islamic sect (`shia` or `sunni`)
- **`source_type`**: Type of source material (`quran`, `hadith`, `history`, `fatwa`, `quote`)
- **`description`**: Optional description of the category
- **`order`**: Display order within the hierarchy
- **`slug`**: URL-friendly identifier (auto-generated from title, unique)
- **`xmind_file`**: URL to associated XMind mind map file (optional)
- **`children_count`**: Number of active child categories
- **`has_hadis`**: Boolean indicating if category contains hadith content (tree endpoints only)
Loading…
Cancel
Save