Browse Source

hadis detail and sync apis

master
Mohsen Taba 5 months ago
parent
commit
f66003a45a
  1. 365
      apps/hadis/docs.py
  2. 16
      apps/hadis/migrations/0014_remove_hadistransmitter_narrator_layer.py
  3. 26
      apps/hadis/migrations/0015_hadistransmitter_narrator_layer.py
  4. 19
      apps/hadis/migrations/0016_remove_hadistransmitter_narrator_layer_and_more.py
  5. 64
      apps/hadis/migrations/0017_narratorlayer_hadistransmitter_narrator_layer.py
  6. 16
      apps/hadis/migrations/0018_remove_hadistransmitter_status.py
  7. 27
      apps/hadis/migrations/0019_hadistransmitter_status.py
  8. 17
      apps/hadis/migrations/0020_hadisreference_description.py
  9. 20
      apps/hadis/migrations/0021_remove_hadisreference_book_reference_and_more.py
  10. 30
      apps/hadis/migrations/0022_hadisreference_book_reference_and_more.py
  11. 29
      apps/hadis/migrations/0023_remove_hadisreference_book_reference_and_more.py
  12. 16
      apps/hadis/migrations/0024_remove_hadisreference_book.py
  13. 25
      apps/hadis/migrations/0025_hadisreference_book_reference.py
  14. 16
      apps/hadis/migrations/0026_remove_hadisreference_book_reference.py
  15. 25
      apps/hadis/migrations/0027_hadisreference_book_reference.py
  16. 17
      apps/hadis/migrations/0028_hadistransmitter_description.py
  17. 21
      apps/hadis/migrations/0029_remove_hadistransmitter_description_and_more.py
  18. 16
      apps/hadis/migrations/0030_remove_hadistransmitter_is_gap.py
  19. 17
      apps/hadis/migrations/0031_hadistransmitter_is_gap.py
  20. 21
      apps/hadis/migrations/0032_remove_hadis_a_hadis_description.py
  21. 57
      apps/hadis/migrations/0033_hadiscorrection.py
  22. 25
      apps/hadis/models/hadis.py
  23. 3
      apps/hadis/models/transmitter.py
  24. 212
      apps/hadis/serializers/hadis.py
  25. 71
      apps/hadis/serializers/reference.py
  26. 12
      apps/hadis/urls.py
  27. 120
      apps/hadis/views/category.py
  28. 18
      apps/hadis/views/hadis.py
  29. 38
      apps/hadis/views/reference.py
  30. 36
      apps/hadis/views/transmitter.py
  31. 635
      docs/SyncHadis.md
  32. 130
      docs/hadisdetail.md

365
apps/hadis/docs.py

@ -52,104 +52,104 @@ hadis_sect_list_swagger = swagger_auto_schema(
# Swagger documentation for HadisCategoryTreeView # Swagger documentation for HadisCategoryTreeView
hadis_category_tree_swagger = swagger_auto_schema( hadis_category_tree_swagger = swagger_auto_schema(
operation_description="Get hierarchical tree structure of Hadis categories for a specific sect, grouped by source type (Quran/Hadith)",
operation_summary="Get Hadis Category Tree by Sect",
operation_description="Get complete hierarchical tree structure of Hadis categories grouped by sect type (shia/sunni), with enhanced child information including father category details and hadis information",
operation_summary="Get Complete Hadis Category Tree",
tags=['Hadis'], tags=['Hadis'],
manual_parameters=[
openapi.Parameter(
'sect_id',
openapi.IN_PATH,
description="ID of the Hadis sect",
type=openapi.TYPE_INTEGER,
required=True
)
],
responses={ responses={
status.HTTP_200_OK: openapi.Response( status.HTTP_200_OK: openapi.Response(
description="Hierarchical tree structure of categories with total count",
description="Complete hierarchical tree structure of categories grouped by sect type with enhanced child information",
examples={ examples={
"application/json": { "application/json": {
"count": 6,
"count": 12,
"results": { "results": {
"quran": [
{
"id": 1,
"name": "Tafsir",
"hadis_count": 150,
"has_hadis": False,
"order": 1,
"xmind_file": "http://example.com/media/xmind/tafsir.xmind",
"has_xmind_file": True,
"children_count": 2,
"children": [
"shia": {
"sects": {
"1": {
"id": 1,
"sect_type": "shia",
"title": "Shi'a Hadith Collections",
"description": "Collections of Shi'a hadith",
"order": 1
}
},
"categories": {
"quran": [
{ {
"id": 2,
"name": "Surah Al-Fatiha",
"hadis_count": 25,
"has_hadis": True,
"id": 1,
"name": "Tafsir",
"hadis_count": 150,
"has_hadis": False,
"order": 1, "order": 1,
"xmind_file": None,
"has_xmind_file": False,
"children_count": 0,
"children": []
},
{
"id": 3,
"name": "Surah Al-Baqarah",
"hadis_count": 125,
"has_hadis": True,
"order": 2,
"xmind_file": "http://example.com/media/xmind/baqarah.xmind",
"xmind_file": "http://example.com/media/xmind/tafsir.xmind",
"has_xmind_file": True, "has_xmind_file": True,
"children_count": 0,
"children": []
"children": [
{
"id": 2,
"name": "Surah Al-Fatiha",
"hadis_count": 25,
"has_hadis": True,
"order": 1,
"father_category": {
"id": 1,
"name": "Tafsir",
"sect_id": 1,
"sect_type": "shia",
"source_type": "quran"
},
"hadis_details": [
{
"id": 1,
"title": "The Opening",
"title_narrator": "From Abu Hurairah",
"text": "Actions are but by intention...",
"translation": "Actions are but by intention...",
"share_link": "http://example.com/hadis/1"
}
],
"children": []
}
]
} }
]
],
"hadith": []
} }
],
"hadith": [
{
"id": 4,
"name": "Sahih Bukhari",
"hadis_count": 300,
"has_hadis": False,
"order": 1,
"xmind_file": "http://example.com/media/xmind/bukhari.xmind",
"has_xmind_file": True,
"children_count": 2,
"children": [
{
"id": 5,
"name": "Book of Faith",
"hadis_count": 50,
"has_hadis": True,
"order": 1,
"xmind_file": None,
"has_xmind_file": False,
"children_count": 0,
"children": []
},
},
"sunni": {
"sects": {
"2": {
"id": 2,
"sect_type": "sunni",
"title": "Sunni Hadith Collections",
"description": "Collections of Sunni hadith",
"order": 2
}
},
"categories": {
"hadith": [
{ {
"id": 6,
"name": "Book of Prayer",
"hadis_count": 250,
"id": 10,
"name": "Sahih al-Bukhari",
"hadis_count": 2500,
"has_hadis": True, "has_hadis": True,
"order": 2,
"xmind_file": "http://example.com/media/xmind/prayer.xmind",
"has_xmind_file": True,
"children_count": 0,
"hadis_details": [
{
"id": 100,
"title": "The Beginning of Revelation",
"title_narrator": "From Aisha",
"text": "The first revelation...",
"translation": "The first revelation...",
"share_link": "http://example.com/hadis/100"
}
],
"children": [] "children": []
} }
] ]
} }
]
}
} }
} }
} }
), ),
status.HTTP_404_NOT_FOUND: openapi.Response(
description="Sect not found"
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error" description="Internal server error"
) )
@ -157,6 +157,9 @@ hadis_category_tree_swagger = swagger_auto_schema(
) )
# Swagger documentation for HadisSyncView
# Swagger documentation for HadisListView # Swagger documentation for HadisListView
hadis_list_swagger = swagger_auto_schema( 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="Get paginated list of Hadis for a specific category with translations based on request language",
@ -408,13 +411,93 @@ hadis_sync_swagger = swagger_auto_schema(
tags=['Hadis'], tags=['Hadis'],
responses={ responses={
status.HTTP_200_OK: openapi.Response( status.HTTP_200_OK: openapi.Response(
description="Complete hadis data for synchronization",
description="Complete hadis data for synchronization with enhanced information",
examples={ examples={
"application/json": { "application/json": {
"categories": [],
"hadis": [],
"references": [],
"transmitters": []
"count": 1500,
"results": {
"1": {
"id": 1,
"number": 1,
"category_id": 2,
"title": "The Opening",
"title_narrator": "From Abu Hurairah",
"text": "Actions are but by intention...",
"description": "This hadith emphasizes the importance of intention in all actions...",
"translations": {
"en": "Actions are but by intention...",
"ar": "إنما الأعمال بالنيات...",
"fa": "اعمال به نیت است..."
},
"explanation": "This hadith emphasizes the importance of intention in all actions...",
"address": "Sahih al-Bukhari, Book of Revelation",
"hadis_status": {
"id": 1,
"title": "Sahih",
"color": "green"
},
"hadis_status_text": "Authentic",
"share_link": "http://example.com/hadis/1",
"tags": [
{"id": 1, "title": "Intention"},
{"id": 2, "title": "Actions"}
],
"links": {
"audio": "http://example.com/audio/hadis1.mp3",
"video": "http://example.com/video/hadis1.mp4"
},
"transmitters": [
{
"id": 1,
"order": 1,
"is_gap": False,
"narrator_layer": "sahaba",
"transmitter": {
"id": 1,
"full_name": "Abu Hurairah",
"birth_year_hijri": 18,
"death_year_hijri": 59,
"madhhab": "sunni",
"description": "One of the most prolific narrators of hadith",
"reliability": "very_reliable"
}
}
],
"references": [
{
"id": 1,
"title": "Sahih al-Bukhari",
"images": [
{
"id": 1,
"image": "http://example.com/media/books/bukhari_cover.jpg",
"order": 1,
"description": "Front cover of Sahih al-Bukhari"
}
],
"authors": [
{
"id": 1,
"name": "Muhammad ibn Isma'il al-Bukhari"
}
],
"description": "The most authentic collection of hadith compiled by Imam Bukhari"
}
],
"corrections": [
{
"id": 1,
"title": "Translation Correction",
"description": "Corrected translation for better accuracy",
"translation": {
"en": "Actions are judged by intentions...",
"ar": "إنما الأعمال بالنيات...",
"fa": "اعمال به نیت ها قضاوت می شود..."
}
}
]
}
}
} }
} }
), ),
@ -559,6 +642,68 @@ transmitter_detail_swagger = swagger_auto_schema(
} }
) )
transmitter_sync_swagger = swagger_auto_schema(
operation_description="Get complete transmitter (narrator) data for offline synchronization including biographical information and scholarly opinions",
operation_summary="Sync Transmitter Data",
operation_id="syncTransmitterData",
tags=['Hadis'],
responses={
status.HTTP_200_OK: openapi.Response(
description="Complete transmitter data for synchronization",
examples={
"application/json": {
"count": 150,
"results": {
"1": {
"id": 1,
"full_name": "Abu Daud Sulaiman ibn al-Ash'ath al-Azdi al-Sijistani",
"biographical": {
"personal_info": {
"full_name": "Abu Daud Sulaiman ibn al-Ash'ath al-Azdi al-Sijistani",
"kunya": "Abu Daud",
"known_as": "Imam Abu Daud",
"nickname": "Al-Sijistani"
},
"dates": {
"birth_year_hijri": 202,
"death_year_hijri": 275,
"age_at_death": 73
},
"locations": {
"origin": "Sijistan (modern Sistan)",
"lived_in": "Basra, Baghdad",
"died_in": "Basra"
},
"religious_profile": {
"reliability": "very_reliable",
"madhhab": "shafii",
"in_sahih_muslim": True,
"in_sahih_bukhari": False
},
"description": "One of the six canonical hadith collectors...",
"thumbnail": "http://example.com/media/transmitters/abu_daud.jpg"
},
"scholars_opinions": [
{
"id": 1,
"scholar_name": "Imam al-Nawawi",
"opinion_text": "Abu Daud is reliable and trustworthy...",
"status": "confirmed",
"created_at": "2025-12-13T10:00:00Z",
"updated_at": "2025-12-13T10:00:00Z"
}
]
}
}
}
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# Swagger documentation for BookReferencesView # Swagger documentation for BookReferencesView
book_references_list_swagger = swagger_auto_schema( book_references_list_swagger = swagger_auto_schema(
@ -603,6 +748,62 @@ book_references_list_swagger = swagger_auto_schema(
} }
) )
reference_sync_swagger = swagger_auto_schema(
operation_description="Get complete book reference data for offline synchronization including basic information, detailed publication info, and related hadises",
operation_summary="Sync Book References Data",
operation_id="syncReferenceData",
tags=['Hadis'],
responses={
status.HTTP_200_OK: openapi.Response(
description="Complete book references data for synchronization",
examples={
"application/json": {
"count": 50,
"results": {
"1": {
"id": 1,
"title": "Sahih al-Bukhari",
"basic_info": {
"title": "Sahih al-Bukhari",
"authors": [
{
"id": 1,
"name": "Muhammad ibn Isma'il al-Bukhari"
}
],
"rating": 5.0,
"description": "The most authentic collection of hadith compiled by Imam Bukhari",
"volume": "9 volumes"
},
"information": {
"language": "Arabic",
"isbn": "978-1234567890",
"year_of_publication": "846",
"number_of_pages": 4200,
"volume_info": "9 volumes",
"rating": 5.0
},
"hadis": [
{
"id": 1,
"title": "The Opening",
"title_narrator": "From Abu Hurairah",
"text": "Actions are but by intention...",
"translation": "Actions are but by intention...",
"share_link": "http://example.com/hadis/1"
}
]
}
}
}
}
),
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response(
description="Internal server error"
)
}
)
# Swagger documentation for BookAuthorView # Swagger documentation for BookAuthorView
book_authors_list_swagger = swagger_auto_schema( book_authors_list_swagger = swagger_auto_schema(

16
apps/hadis/migrations/0014_remove_hadistransmitter_narrator_layer.py

@ -0,0 +1,16 @@
# Generated by Django 5.2.9 on 2025-12-13 08:55
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("hadis", "0013_hadis_title_narrator"),
]
operations = [
migrations.RemoveField(
model_name="hadistransmitter",
name="narrator_layer",
),
]

26
apps/hadis/migrations/0015_hadistransmitter_narrator_layer.py

@ -0,0 +1,26 @@
# Generated by Django 5.2.9 on 2025-12-13 08:56
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0014_remove_hadistransmitter_narrator_layer"),
]
operations = [
migrations.AddField(
model_name="hadistransmitter",
name="narrator_layer",
field=models.ForeignKey(
blank=True,
help_text="The layer/class (Tabaqah) this narrator belongs to",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="transmitters",
to="hadis.narratorlayer",
verbose_name="narrator layer",
),
),
]

19
apps/hadis/migrations/0016_remove_hadistransmitter_narrator_layer_and_more.py

@ -0,0 +1,19 @@
# Generated by Django 5.2.9 on 2025-12-13 08:57
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("hadis", "0015_hadistransmitter_narrator_layer"),
]
operations = [
migrations.RemoveField(
model_name="hadistransmitter",
name="narrator_layer",
),
migrations.DeleteModel(
name="NarratorLayer",
),
]

64
apps/hadis/migrations/0017_narratorlayer_hadistransmitter_narrator_layer.py

@ -0,0 +1,64 @@
# Generated by Django 5.2.9 on 2025-12-13 08:58
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0016_remove_hadistransmitter_narrator_layer_and_more"),
]
operations = [
migrations.CreateModel(
name="NarratorLayer",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=255, verbose_name="name")),
(
"number",
models.PositiveIntegerField(
unique=True, verbose_name="layer number"
),
),
(
"description",
models.TextField(blank=True, null=True, verbose_name="description"),
),
(
"created_at",
models.DateTimeField(auto_now_add=True, verbose_name="created at"),
),
(
"updated_at",
models.DateTimeField(auto_now=True, verbose_name="updated at"),
),
],
options={
"verbose_name": "Narrator Layer",
"verbose_name_plural": "Narrator Layers",
"ordering": ["number"],
},
),
migrations.AddField(
model_name="hadistransmitter",
name="narrator_layer",
field=models.ForeignKey(
blank=True,
help_text="The layer/class (Tabaqah) this narrator belongs to",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="transmitters",
to="hadis.narratorlayer",
verbose_name="narrator layer",
),
),
]

16
apps/hadis/migrations/0018_remove_hadistransmitter_status.py

@ -0,0 +1,16 @@
# Generated by Django 5.2.9 on 2025-12-13 09:02
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("hadis", "0017_narratorlayer_hadistransmitter_narrator_layer"),
]
operations = [
migrations.RemoveField(
model_name="hadistransmitter",
name="status",
),
]

27
apps/hadis/migrations/0019_hadistransmitter_status.py

@ -0,0 +1,27 @@
# Generated by Django 5.2.9 on 2025-12-13 09:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0018_remove_hadistransmitter_status"),
]
operations = [
migrations.AddField(
model_name="hadistransmitter",
name="status",
field=models.CharField(
choices=[
("reliable", "Reliable"),
("weak", "Weak"),
("unknown", "Unknown"),
],
default="unknown",
help_text="Reliability status of the narrator",
max_length=20,
verbose_name="reliability status",
),
),
]

17
apps/hadis/migrations/0020_hadisreference_description.py

@ -0,0 +1,17 @@
# Generated by Django 5.2.9 on 2025-12-13 09:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0019_hadistransmitter_status"),
]
operations = [
migrations.AddField(
model_name="hadisreference",
name="description",
field=models.TextField(blank=True, null=True, verbose_name="description"),
),
]

20
apps/hadis/migrations/0021_remove_hadisreference_book_reference_and_more.py

@ -0,0 +1,20 @@
# Generated by Django 5.2.9 on 2025-12-13 09:55
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("hadis", "0020_hadisreference_description"),
]
operations = [
migrations.RemoveField(
model_name="hadisreference",
name="book_reference",
),
migrations.RemoveField(
model_name="hadisreference",
name="description",
),
]

30
apps/hadis/migrations/0022_hadisreference_book_reference_and_more.py

@ -0,0 +1,30 @@
# Generated by Django 5.2.9 on 2025-12-13 09:56
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0021_remove_hadisreference_book_reference_and_more"),
]
operations = [
migrations.AddField(
model_name="hadisreference",
name="book_reference",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="hadis_references",
to="hadis.bookreference",
verbose_name="book reference",
),
),
migrations.AddField(
model_name="hadisreference",
name="description",
field=models.TextField(blank=True, null=True, verbose_name="description"),
),
]

29
apps/hadis/migrations/0023_remove_hadisreference_book_reference_and_more.py

@ -0,0 +1,29 @@
# Generated by Django 5.2.9 on 2025-12-13 10:00
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0022_hadisreference_book_reference_and_more"),
]
operations = [
migrations.RemoveField(
model_name="hadisreference",
name="book_reference",
),
migrations.AddField(
model_name="hadisreference",
name="book",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="hadis_references",
to="hadis.bookreference",
verbose_name="book reference",
),
),
]

16
apps/hadis/migrations/0024_remove_hadisreference_book.py

@ -0,0 +1,16 @@
# Generated by Django 5.2.9 on 2025-12-13 10:01
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("hadis", "0023_remove_hadisreference_book_reference_and_more"),
]
operations = [
migrations.RemoveField(
model_name="hadisreference",
name="book",
),
]

25
apps/hadis/migrations/0025_hadisreference_book_reference.py

@ -0,0 +1,25 @@
# Generated by Django 5.2.9 on 2025-12-13 10:02
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0024_remove_hadisreference_book"),
]
operations = [
migrations.AddField(
model_name="hadisreference",
name="book_reference",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="hadis_references",
to="hadis.bookreference",
verbose_name="book reference",
),
),
]

16
apps/hadis/migrations/0026_remove_hadisreference_book_reference.py

@ -0,0 +1,16 @@
# Generated by Django 5.2.9 on 2025-12-13 10:03
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("hadis", "0025_hadisreference_book_reference"),
]
operations = [
migrations.RemoveField(
model_name="hadisreference",
name="book_reference",
),
]

25
apps/hadis/migrations/0027_hadisreference_book_reference.py

@ -0,0 +1,25 @@
# Generated by Django 5.2.9 on 2025-12-13 10:05
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0026_remove_hadisreference_book_reference"),
]
operations = [
migrations.AddField(
model_name="hadisreference",
name="book_reference",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="hadis_references",
to="hadis.bookreference",
verbose_name="book reference",
),
),
]

17
apps/hadis/migrations/0028_hadistransmitter_description.py

@ -0,0 +1,17 @@
# Generated by Django 5.2.9 on 2025-12-13 10:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0027_hadisreference_book_reference"),
]
operations = [
migrations.AddField(
model_name="hadistransmitter",
name="description",
field=models.TextField(blank=True, null=True, verbose_name="description"),
),
]

21
apps/hadis/migrations/0029_remove_hadistransmitter_description_and_more.py

@ -0,0 +1,21 @@
# Generated by Django 5.2.9 on 2025-12-13 10:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0028_hadistransmitter_description"),
]
operations = [
migrations.RemoveField(
model_name="hadistransmitter",
name="description",
),
migrations.AddField(
model_name="hadistransmitter",
name="is_gap",
field=models.BooleanField(default=False, verbose_name="is gap"),
),
]

16
apps/hadis/migrations/0030_remove_hadistransmitter_is_gap.py

@ -0,0 +1,16 @@
# Generated by Django 5.2.9 on 2025-12-13 10:39
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("hadis", "0029_remove_hadistransmitter_description_and_more"),
]
operations = [
migrations.RemoveField(
model_name="hadistransmitter",
name="is_gap",
),
]

17
apps/hadis/migrations/0031_hadistransmitter_is_gap.py

@ -0,0 +1,17 @@
# Generated by Django 5.2.9 on 2025-12-13 10:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0030_remove_hadistransmitter_is_gap"),
]
operations = [
migrations.AddField(
model_name="hadistransmitter",
name="is_gap",
field=models.BooleanField(default=False, verbose_name="is gap"),
),
]

21
apps/hadis/migrations/0032_remove_hadis_a_hadis_description.py

@ -0,0 +1,21 @@
# Generated by Django 5.2.9 on 2025-12-13 10:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0031_hadistransmitter_is_gap"),
]
operations = [
migrations.RemoveField(
model_name="hadis",
name="a",
),
migrations.AddField(
model_name="hadis",
name="description",
field=models.TextField(blank=True, null=True, verbose_name="description"),
),
]

57
apps/hadis/migrations/0033_hadiscorrection.py

@ -0,0 +1,57 @@
# Generated by Django 5.2.9 on 2025-12-13 11:39
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0032_remove_hadis_a_hadis_description"),
]
operations = [
migrations.CreateModel(
name="HadisCorrection",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.CharField(max_length=255, verbose_name="title")),
(
"description",
models.TextField(blank=True, null=True, verbose_name="description"),
),
(
"translation",
models.JSONField(default=list, verbose_name="translation"),
),
(
"created_at",
models.DateTimeField(auto_now_add=True, verbose_name="created at"),
),
(
"updated_at",
models.DateTimeField(auto_now=True, verbose_name="updated at"),
),
(
"hadis",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="hadis.hadis",
verbose_name="hadis correction",
),
),
],
options={
"verbose_name": "Hadis Correction",
"verbose_name_plural": "Hadis Corrections",
"ordering": ("-created_at",),
},
),
]

25
apps/hadis/models/hadis.py

@ -1,9 +1,10 @@
from django.db import models from django.db import models
from django.db.models import F
from django.db.models import F, ForeignKey
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.conf import settings from django.conf import settings
from django.utils.text import slugify from django.utils.text import slugify
from filer.fields.image import FilerImageField from filer.fields.image import FilerImageField
from .reference import BookReference
class HadisCollection(models.Model): class HadisCollection(models.Model):
@ -100,7 +101,7 @@ class Hadis(models.Model):
number = models.PositiveIntegerField(verbose_name=_('number'), default=1) number = models.PositiveIntegerField(verbose_name=_('number'), default=1)
title_narrator = models.CharField(max_length=255, verbose_name=_('title narrator'), null=True, blank=True) 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) title = models.CharField(max_length=255, verbose_name=_('title'), null=True, blank=True)
a =models.IntegerField(blank=True ,null=True)
description = models.TextField(verbose_name=_('description'), blank=True, null=True)
text = models.TextField(verbose_name=_('text')) text = models.TextField(verbose_name=_('text'))
translation = models.JSONField(verbose_name=_('translation'), default=list) translation = models.JSONField(verbose_name=_('translation'), default=list)
@ -158,15 +159,18 @@ class HadisReference(models.Model):
related_name='references' related_name='references'
) )
book_reference = models.ForeignKey( book_reference = models.ForeignKey(
"hadis.BookReference",
BookReference,
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
null=True, null=True,
blank=True, blank=True,
verbose_name=_('book reference'), verbose_name=_('book reference'),
related_name='hadis_references' related_name='hadis_references'
) )
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at')) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at'))
description = models.TextField(verbose_name=_('description'), null=True, blank=True)
class Meta: class Meta:
verbose_name = _('Hadis Reference') verbose_name = _('Hadis Reference')
verbose_name_plural = _('Hadis References') verbose_name_plural = _('Hadis References')
@ -201,3 +205,18 @@ class ReferenceImage(models.Model):
super().save(*args, **kwargs) super().save(*args, **kwargs)
class HadisCorrection(models.Model):
hadis = models.ForeignKey(Hadis, verbose_name=_("hadis correction"), on_delete=models.CASCADE)
title = models.CharField(max_length=255, verbose_name=_("title"))
description = models.TextField(verbose_name=_("description"), blank=True, null=True)
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"))
class Meta:
verbose_name = _("Hadis Correction")
verbose_name_plural = _("Hadis Corrections")
ordering = ("-created_at",)
def __str__(self):
return f"{self.hadis.number} - {self.title}"

3
apps/hadis/models/transmitter.py

@ -149,9 +149,10 @@ class HadisTransmitter(models.Model):
verbose_name=_('Order'), verbose_name=_('Order'),
help_text=_('Order in the chain of transmission') help_text=_('Order in the chain of transmission')
) )
is_gap = models.BooleanField(default=False, verbose_name=_('is gap'))
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at')) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at'))
class Meta: class Meta:
verbose_name = _('Hadis Transmitter') verbose_name = _('Hadis Transmitter')
verbose_name_plural = _('Hadis Transmitters') verbose_name_plural = _('Hadis Transmitters')

212
apps/hadis/serializers/hadis.py

@ -5,7 +5,7 @@ from urllib3 import fields
from ..models import ( from ..models import (
Hadis, HadisStatus, HadisTag, HadisTransmitter, Hadis, HadisStatus, HadisTag, HadisTransmitter,
HadisReference, ReferenceImage, Transmitters, HadisCollection, HadisReference, ReferenceImage, Transmitters, HadisCollection,
TransmitterOpinion ,
TransmitterOpinion, BookReference, BookReferenceImage, BookAuthor, HadisCorrection
) )
from apps.library.serializers import BookSerializer from apps.library.serializers import BookSerializer
@ -31,13 +31,18 @@ class HadisSyncSerializer(serializers.ModelSerializer):
translations = serializers.SerializerMethodField() translations = serializers.SerializerMethodField()
hadis_status = serializers.SerializerMethodField() hadis_status = serializers.SerializerMethodField()
tags = serializers.SerializerMethodField() tags = serializers.SerializerMethodField()
transmitters = serializers.SerializerMethodField()
description = serializers.SerializerMethodField()
references = serializers.SerializerMethodField()
corrections = serializers.SerializerMethodField()
class Meta: class Meta:
model = Hadis model = Hadis
fields = [ fields = [
'id', 'number', 'category_id', 'title', 'title_narrator', 'id', 'number', 'category_id', 'title', 'title_narrator',
'text', 'translations', 'explanation', 'address',
'hadis_status', 'hadis_status_text', 'share_link', 'tags', 'links'
'text', 'translations', 'explanation', 'address', 'description',
'hadis_status', 'hadis_status_text', 'share_link', 'tags', 'links',
'transmitters', 'references', 'corrections'
] ]
def get_translations(self, obj): def get_translations(self, obj):
@ -66,6 +71,75 @@ class HadisSyncSerializer(serializers.ModelSerializer):
"""Get tags""" """Get tags"""
return [{'id': tag.id, 'title': tag.title} for tag in obj.tags.all()] return [{'id': tag.id, 'title': tag.title} for tag in obj.tags.all()]
def get_transmitters(self, obj):
"""Get transmitters with their details"""
transmitters_data = []
for transmitter_rel in obj.transmitters.all().order_by('order'):
transmitter_info = {
'id': transmitter_rel.id,
'order': transmitter_rel.order,
'is_gap': transmitter_rel.is_gap,
'narrator_layer': transmitter_rel.narrator_layer,
'transmitter': {
'id': transmitter_rel.transmitter.id,
'full_name': transmitter_rel.transmitter.full_name,
'birth_year_hijri': transmitter_rel.transmitter.birth_year_hijri,
'death_year_hijri': transmitter_rel.transmitter.death_year_hijri,
'madhhab': transmitter_rel.transmitter.madhhab,
'description': transmitter_rel.transmitter.description,
'reliability': transmitter_rel.transmitter.reliability
}
}
transmitters_data.append(transmitter_info)
return transmitters_data
def get_description(self, obj):
"""Get hadis description"""
return getattr(obj, 'description', None)
def get_references(self, obj):
"""Get references with book information"""
references_data = []
for reference in obj.references.all():
try:
book = reference.book_reference
reference_info = {
'id': reference.id,
'title': book.title if book else None,
'images': [
{
'id': img.id,
'image': img.image.url if img.image else None,
'order': img.order,
'description': img.description
} for img in book.images.all() if book
] if book else [],
'authors': [
{
'id': author.id,
'name': author.name
} for author in book.authors.all() if book
] if book else [],
'description': book.description if book else None
}
references_data.append(reference_info)
except:
continue
return references_data
def get_corrections(self, obj):
"""Get hadis corrections"""
corrections_data = []
for correction in obj.hadiscorrection_set.all():
correction_info = {
'id': correction.id,
'title': correction.title,
'description': correction.description,
'translation': correction.translation
}
corrections_data.append(correction_info)
return corrections_data
class HadisListSerializer(serializers.ModelSerializer): class HadisListSerializer(serializers.ModelSerializer):
"""Serializer for Hadis list""" """Serializer for Hadis list"""
@ -155,6 +229,65 @@ class TransmitterDetailSerializer(serializers.ModelSerializer):
] ]
class TransmitterSyncSerializer(serializers.ModelSerializer):
"""Serializer for syncing all transmitter data for offline mode"""
# Biographical data group
biographical = serializers.SerializerMethodField()
# Scholar's opinions group
scholars_opinions = serializers.SerializerMethodField()
class Meta:
model = Transmitters
fields = [
'id', 'full_name', 'biographical', 'scholars_opinions'
]
def get_biographical(self, obj):
"""Get biographical information"""
return {
'personal_info': {
'full_name': obj.full_name,
'kunya': obj.kunya,
'known_as': obj.known_as,
'nickname': obj.nickname,
},
'dates': {
'birth_year_hijri': obj.birth_year_hijri,
'death_year_hijri': obj.death_year_hijri,
'age_at_death': obj.age_at_death,
},
'locations': {
'origin': obj.origin,
'lived_in': obj.lived_in,
'died_in': obj.died_in,
},
'religious_profile': {
'reliability': obj.reliability,
'madhhab': obj.madhhab,
'in_sahih_muslim': obj.in_sahih_muslim,
'in_sahih_bukhari': obj.in_sahih_bukhari,
},
'description': obj.description,
'thumbnail': obj.thumbnail.url if obj.thumbnail else None,
}
def get_scholars_opinions(self, obj):
"""Get all scholarly opinions about this transmitter"""
opinions = []
for opinion in obj.opinions.all():
opinions.append({
'id': opinion.id,
'scholar_name': opinion.scholar_name,
'opinion_text': opinion.opinion_text,
'status': opinion.status,
'created_at': opinion.created_at.isoformat() if opinion.created_at else None,
'updated_at': opinion.updated_at.isoformat() if opinion.updated_at else None,
})
return opinions
class HadisTransmitterSerializer(serializers.ModelSerializer): class HadisTransmitterSerializer(serializers.ModelSerializer):
"""Serializer for HadisTransmitter with transmitter details""" """Serializer for HadisTransmitter with transmitter details"""
@ -163,7 +296,7 @@ class HadisTransmitterSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = HadisTransmitter model = HadisTransmitter
fields = [ fields = [
'id', 'transmitter', 'order', 'is_gap'
'id', 'transmitter', 'order', 'is_gap','narrator_layer'
] ]
@ -187,28 +320,76 @@ class ReferenceImageSerializer(serializers.ModelSerializer):
class HadisReferenceSerializer(serializers.ModelSerializer): class HadisReferenceSerializer(serializers.ModelSerializer):
"""Serializer for HadisReference with book and images""" """Serializer for HadisReference with book and images"""
book = BookSerializer(read_only=True)
images = ReferenceImageSerializer(many=True, read_only=True)
book_title = serializers.SerializerMethodField()
book_images = serializers.SerializerMethodField()
book_authors = serializers.SerializerMethodField()
book_description = serializers.SerializerMethodField()
class Meta: class Meta:
model = HadisReference model = HadisReference
fields = [ fields = [
'id', 'book', 'page_number', 'hadis_number_in_book',
'description', 'images'
'id', 'book_title', 'book_images', 'book_authors', 'book_description'
] ]
def get_book_title(self, obj):
"""Get book title"""
try :
title = obj.book_reference.title
return title
except:
return None
def get_book_images(self, obj):
"""Get book images"""
try :
images = obj.book_reference.images.all()
return images
except:
return None
def get_book_authors(self, obj):
"""Get book authors"""
try :
authors = obj.book_reference.authors.all()
return authors
except:
return None
def get_book_description(self, obj):
"""Get book description"""
try :
description = obj.book_reference.description
return description
except:
return None
class HadisCorrectionSerializer(serializers.ModelSerializer):
"""Serializer for HadisCorrection"""
hadis_translation = serializers.SerializerMethodField()
class Meta:
model = HadisCorrection
fields = ['id', 'title', 'description', 'hadis_translation', 'created_at', 'updated_at']
def get_hadis_translation(self, obj):
"""Get translation based on request language"""
request = self.context.get('request')
language_code = getattr(request, 'LANGUAGE_CODE', 'en')
return obj.translation.get(language_code, '')
class HadisDetailSerializer(serializers.ModelSerializer): class HadisDetailSerializer(serializers.ModelSerializer):
"""Detailed serializer for Hadis with all related objects""" """Detailed serializer for Hadis with all related objects"""
hadis_status = HadisStatusSerializer(read_only=True) hadis_status = HadisStatusSerializer(read_only=True)
tags = HadisTagSerializer(many=True, read_only=True) tags = HadisTagSerializer(many=True, read_only=True)
transmitters = HadisTransmitterSerializer( transmitters = HadisTransmitterSerializer(
source='hadistransmitter_set',
many=True, many=True,
read_only=True read_only=True
) )
references = HadisReferenceSerializer( references = HadisReferenceSerializer(
source='hadisreference_set',
many=True,
read_only=True
)
corrections = HadisCorrectionSerializer(
source='hadiscorrection_set',
many=True, many=True,
read_only=True read_only=True
) )
@ -218,9 +399,10 @@ class HadisDetailSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Hadis model = Hadis
fields = [ fields = [
'id', 'number', 'title', 'text', 'translation', 'explanation',
'address', 'hadis_status_text', 'links', 'status',
'category', 'hadis_status', 'tags', 'transmitters', 'references'
'id', 'number', 'title', 'title_narrator','text', 'translation', 'explanation',
'address', 'hadis_status_text', 'links','share_link', 'status',
'category', 'hadis_status', 'tags', 'transmitters', 'description',
'references', 'corrections'
] ]
def get_category(self, obj): def get_category(self, obj):
@ -229,7 +411,7 @@ class HadisDetailSerializer(serializers.ModelSerializer):
return { return {
'id': obj.category.id, 'id': obj.category.id,
'title': obj.category.title, 'title': obj.category.title,
'category_type': obj.category.category_type
'category_type': obj.category.content_type
} }
return None return None

71
apps/hadis/serializers/reference.py

@ -1,7 +1,7 @@
from rest_framework import serializers from rest_framework import serializers
from ..serializers import HadisListSerializer from ..serializers import HadisListSerializer
from ..models import BookReference , BookAuthor , BookReferenceImage
from ..models import BookReference , BookAuthor , BookReferenceImage, HadisReference
class BookAuthorSerializer(serializers.ModelSerializer): class BookAuthorSerializer(serializers.ModelSerializer):
class Meta: class Meta:
@ -57,3 +57,72 @@ class BookDetailSerializer(serializers.ModelSerializer):
# author = validated_data.pop('author') # author = validated_data.pop('author')
# book = BookReference.objects.create(**validated_data) # book = BookReference.objects.create(**validated_data)
# for author in author # for author in author
class BookReferenceSyncSerializer(serializers.ModelSerializer):
"""Serializer for syncing all book reference data for offline mode"""
# Basic information
basic_info = serializers.SerializerMethodField()
# Information group (detailed publication info)
information = serializers.SerializerMethodField()
# Hadis group (related hadises)
hadis = serializers.SerializerMethodField()
class Meta:
model = BookReference
fields = [
'id', 'title', 'basic_info', 'information', 'hadis'
]
def get_basic_info(self, obj):
"""Get basic book information including authors and rating"""
authors = []
try:
for author in obj.authors.all():
authors.append({
'id': author.id,
'name': author.name
})
except:
authors = []
return {
'title': obj.title,
'authors': authors,
'rating': obj.rate,
'description': obj.description,
'volume': obj.volume
}
def get_information(self, obj):
"""Get detailed publication information"""
return {
'language': obj.language,
'isbn': obj.isbn,
'year_of_publication': obj.year_of_publication,
'number_of_pages': obj.number_page,
'volume_info': obj.volume,
'rating': obj.rate
}
def get_hadis(self, obj):
"""Get all hadises related to this book reference"""
hadis_list = []
try:
for hadis_ref in obj.hadis_references.all():
hadis = hadis_ref.hadis
hadis_list.append({
'id': hadis.id,
'title': hadis.title,
'title_narrator': hadis.title_narrator,
'text': hadis.text,
'translation': hadis.get_translation(self.context.get('request').LANGUAGE_CODE if self.context.get('request') else 'en'),
'share_link': hadis.share_link
})
except:
pass
return hadis_list

12
apps/hadis/urls.py

@ -1,8 +1,8 @@
from django.urls import path from django.urls import path
from .views.category import HadisCategorySectListView, HadisCategoryTreeView, CategoriesView, CategoriesBySectView, HadisCategorySelectBySectView, HadisCategorySelectBySectSourceView , HadisCategoryTreeNormalView from .views.category import HadisCategorySectListView, HadisCategoryTreeView, CategoriesView, CategoriesBySectView, HadisCategorySelectBySectView, HadisCategorySelectBySectSourceView , HadisCategoryTreeNormalView
from .views.hadis import HadisCollectionListView, HadisListView, HadisDetailView, HadisSyncView from .views.hadis import HadisCollectionListView, HadisListView, HadisDetailView, HadisSyncView
from .views.transmitter import TransmitterView ,TransmitterDetailView
from .views.reference import BookDetailView, BookReferencesView
from .views.transmitter import TransmitterView ,TransmitterDetailView, TransmitterSyncView
from .views.reference import BookDetailView, BookReferencesView, BookReferenceSyncView
from .views.info import HadisInfoView from .views.info import HadisInfoView
@ -12,9 +12,13 @@ urlpatterns = [
path('sync/categories/tree/', HadisCategoryTreeView.as_view(), name='hadis-category-tree'), path('sync/categories/tree/', HadisCategoryTreeView.as_view(), name='hadis-category-tree'),
path('categories/tree/', HadisCategoryTreeNormalView.as_view(), name='hadis-category-tree-normal'), path('categories/tree/', HadisCategoryTreeNormalView.as_view(), name='hadis-category-tree-normal'),
path('sync/hadis/', HadisSyncView.as_view(), name='hadis-sync'), path('sync/hadis/', HadisSyncView.as_view(), name='hadis-sync'),
path('sync/narrators/', TransmitterSyncView.as_view(), name='transmitter-sync'),
path('sync/references/', BookReferenceSyncView.as_view(), name='reference-sync'),
path('info/', HadisInfoView.as_view(), name='hadis-info'), path('info/', HadisInfoView.as_view(), name='hadis-info'),
path('category/<int:category_id>/', HadisListView.as_view(), name='hadis-list'), path('category/<int:category_id>/', HadisListView.as_view(), name='hadis-list'),
path('<int:hadis_id>/', HadisDetailView.as_view(), name='hadis-detail'),
#path('<int:hadis_id>/', HadisDetailView.as_view(), name='hadis-detail'),
#path('hadis/<int:hadis_id>/transmitters', HadisDetailView.as_view(), name='hadis-detail'),
#path('hadis/<int:hadis_id>/corrections', 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>/<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>/<str:slug>/', HadisCategorySelectBySectView.as_view(), name='categories-tree-by-sect'),
path('categories/<str:sect_type>/', CategoriesBySectView.as_view(), name='categories-by-sect'), path('categories/<str:sect_type>/', CategoriesBySectView.as_view(), name='categories-by-sect'),
@ -23,6 +27,4 @@ urlpatterns = [
path('narrators/<int:transmitters_id>',TransmitterDetailView.as_view(), name='narrator-detail'), path('narrators/<int:transmitters_id>',TransmitterDetailView.as_view(), name='narrator-detail'),
path('references/',BookReferencesView.as_view(), name='references'), path('references/',BookReferencesView.as_view(), name='references'),
path('references/<int:bookreference_id>',BookDetailView.as_view(), name='reference-detail'), path('references/<int:bookreference_id>',BookDetailView.as_view(), name='reference-detail'),
] ]

120
apps/hadis/views/category.py

@ -83,33 +83,34 @@ class HadisCategoryTreeView(ListAPIView):
serializer_instance = HadisCategoryTreeSerializer(context={'request': request}) serializer_instance = HadisCategoryTreeSerializer(context={'request': request})
# گروه‌بندی بر اساس sect
# گروه‌بندی بر اساس sect_type (shia/sunni)
for category in queryset: for category in queryset:
sect_id = str(category.sect.id)
sect_type = category.sect.sect_type
if sect_id not in grouped_data:
# اضافه کردن اطلاعات sect
grouped_data[sect_id] = {
'sect_info': {
'id': category.sect.id,
'sect_type': category.sect.sect_type,
'title': category.sect.title,
'description': category.sect.description
},
'source_types': [],
if sect_type not in grouped_data:
# ایجاد گروه برای هر sect_type
grouped_data[sect_type] = {
'sects': {},
'categories': {} 'categories': {}
} }
# اضافه کردن source_type به لیست
if category.source_type not in grouped_data[sect_id]['source_types']:
grouped_data[sect_id]['source_types'].append(category.source_type)
# اضافه کردن اطلاعات sect به گروه sect_type
sect_id = str(category.sect.id)
if sect_id not in grouped_data[sect_type]['sects']:
grouped_data[sect_type]['sects'][sect_id] = {
'id': category.sect.id,
'sect_type': category.sect.sect_type,
'title': category.sect.title,
'description': category.sect.description,
'order': category.sect.order
}
# گروه‌بندی categories بر اساس source_type # گروه‌بندی categories بر اساس source_type
if category.source_type not in grouped_data[sect_id]['categories']:
grouped_data[sect_id]['categories'][category.source_type] = []
if category.source_type not in grouped_data[sect_type]['categories']:
grouped_data[sect_type]['categories'][category.source_type] = []
category_data = serializer_instance.to_dict(category)
grouped_data[sect_id]['categories'][category.source_type].append(category_data)
category_data = self.build_enhanced_category_tree(category, serializer_instance)
grouped_data[sect_type]['categories'][category.source_type].append(category_data)
def count_children(children_list): def count_children(children_list):
count = 0 count = 0
@ -120,8 +121,8 @@ class HadisCategoryTreeView(ListAPIView):
return count return count
total_count = 0 total_count = 0
for sect_data in grouped_data.values():
for source_categories in sect_data['categories'].values():
for sect_type_data in grouped_data.values():
for source_categories in sect_type_data['categories'].values():
for item in source_categories: for item in source_categories:
total_count += 1 total_count += 1
if 'children' in item and item['children']: if 'children' in item and item['children']:
@ -134,6 +135,83 @@ class HadisCategoryTreeView(ListAPIView):
return Response(response_data) return Response(response_data)
def build_enhanced_category_tree(self, category, serializer_instance):
"""Build enhanced category tree with father category info and hadis details"""
base_data = serializer_instance.to_dict(category)
# Enhance children with additional information
enhanced_children = []
for child_data in base_data.get('children', []):
enhanced_child = self.enhance_child_data(child_data, category, serializer_instance)
enhanced_children.append(enhanced_child)
base_data['children'] = enhanced_children
return base_data
def enhance_child_data(self, child_data, parent_category, serializer_instance):
"""Enhance child data with father category info and hadis details"""
from ..models import Hadis
# Add father category information
child_data['father_category'] = {
'id': parent_category.id,
'name': parent_category.title,
'sect_id': parent_category.sect.id,
'sect_type': parent_category.sect.sect_type,
'source_type': parent_category.source_type
}
# If this child has no children but has hadis, add hadis details
if not child_data.get('children', []) and child_data.get('has_hadis', False):
try:
# Get the category object
from ..models import HadisCategory
child_category = HadisCategory.objects.get(id=child_data['id'])
# Get hadis for this category
hadis_list = Hadis.objects.filter(
category=child_category,
status=True
).order_by('number')
hadis_details = []
for hadis in hadis_list:
hadis_detail = {
'id': hadis.id,
'title': hadis.title,
'title_narrator': hadis.title_narrator,
'text': hadis.text,
'translation': hadis.get_translation(
self.request.LANGUAGE_CODE if hasattr(self, 'request') and self.request else 'en'
),
'share_link': hadis.share_link
}
hadis_details.append(hadis_detail)
child_data['hadis_details'] = hadis_details
except Exception as e:
# If there's any error, just continue without hadis details
pass
# Recursively enhance children's children
if child_data.get('children', []):
enhanced_grandchildren = []
try:
from ..models import HadisCategory
child_category = HadisCategory.objects.get(id=child_data['id'])
for grandchild_data in child_data['children']:
enhanced_grandchild = self.enhance_child_data(grandchild_data, child_category, serializer_instance)
enhanced_grandchildren.append(enhanced_grandchild)
except:
# If there's an error, keep original children
enhanced_grandchildren = child_data['children']
child_data['children'] = enhanced_grandchildren
return child_data
class HadisCategoryTreeNormalView(ListAPIView): class HadisCategoryTreeNormalView(ListAPIView):
""" """

18
apps/hadis/views/hadis.py

@ -33,7 +33,13 @@ class HadisSyncView(ListAPIView):
def get_queryset(self): def get_queryset(self):
return Hadis.objects.filter(status=True).select_related( return Hadis.objects.filter(status=True).select_related(
'category', 'hadis_status' 'category', 'hadis_status'
).prefetch_related('tags').order_by('id')
).prefetch_related(
'tags',
'transmitters__transmitter',
'references__book_reference__images',
'references__book_reference__authors',
'hadiscorrection_set'
).order_by('id')
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
queryset = self.get_queryset() queryset = self.get_queryset()
@ -90,7 +96,11 @@ class HadisDetailView(RetrieveAPIView):
'category', 'hadis_status' 'category', 'hadis_status'
).prefetch_related( ).prefetch_related(
'tags', 'tags',
'hadistransmitter_set__transmitter',
'hadisreference_set__book',
'hadisreference_set__images'
'transmitters__transmitter',
'references__book_reference__title',
'references__book_reference__images',
'references__book_reference__authors',
'references__book_reference__id',
'references__book_reference__description',
'hadiscorrection_set',
) )

38
apps/hadis/views/reference.py

@ -1,7 +1,8 @@
from rest_framework.generics import ListAPIView, RetrieveAPIView from rest_framework.generics import ListAPIView, RetrieveAPIView
from rest_framework.response import Response
from ..models import BookReference , BookAuthor , BookReferenceImage 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 ..serializers.reference import BookAuthorSerializer, BookDetailSerializer , BookReferenceSerializer, BookReferenceSyncSerializer
from ..docs import book_references_list_swagger, book_authors_list_swagger, book_detail_swagger, reference_sync_swagger
from utils.pagination import NoPagination from utils.pagination import NoPagination
@ -39,6 +40,39 @@ class BookDetailView(RetrieveAPIView):
) )
class BookReferenceSyncView(ListAPIView):
"""
API view to sync all book reference data for offline mode
Returns all book references with basic info, detailed information, and related hadises
"""
serializer_class = BookReferenceSyncSerializer
pagination_class = NoPagination
@reference_sync_swagger
def get_queryset(self):
return BookReference.objects.prefetch_related(
'authors',
'hadis_references__hadis'
).order_by('id')
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True, context={'request': request})
# Group book references by ID for easy lookup
grouped_data = {}
for book_data in serializer.data:
book_id = str(book_data['id'])
grouped_data[book_id] = book_data
response_data = {
'count': queryset.count(),
'results': grouped_data
}
return Response(response_data)

36
apps/hadis/views/transmitter.py

@ -1,8 +1,9 @@
from django.contrib.admin.utils import lookup_field from django.contrib.admin.utils import lookup_field
from rest_framework.generics import ListAPIView , RetrieveAPIView from rest_framework.generics import ListAPIView , RetrieveAPIView
from rest_framework.response import Response
from ..models import Transmitters , TransmitterOpinion from ..models import Transmitters , TransmitterOpinion
from ..serializers import TransmitterSerializer , TransmitterDetailSerializer
from ..docs import transmitter_list_swagger, transmitter_detail_swagger
from ..serializers import TransmitterSerializer , TransmitterDetailSerializer, TransmitterSyncSerializer
from ..docs import transmitter_list_swagger, transmitter_detail_swagger, transmitter_sync_swagger
from utils.pagination import NoPagination from utils.pagination import NoPagination
class TransmitterView(ListAPIView): class TransmitterView(ListAPIView):
@ -52,3 +53,34 @@ class TransmitterDetailView(RetrieveAPIView):
def get_queryset(self): def get_queryset(self):
input = self.kwargs['transmitters_id'] input = self.kwargs['transmitters_id']
return Transmitters.objects.filter(id=input) return Transmitters.objects.filter(id=input)
class TransmitterSyncView(ListAPIView):
"""
API view to sync all transmitter data for offline mode
Returns all transmitters with biographical data and scholarly opinions
"""
serializer_class = TransmitterSyncSerializer
pagination_class = NoPagination
@transmitter_sync_swagger
def get_queryset(self):
return Transmitters.objects.prefetch_related('opinions').order_by('id')
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True, context={'request': request})
# Group transmitters by ID for easy lookup
grouped_data = {}
for transmitter_data in serializer.data:
transmitter_id = str(transmitter_data['id'])
grouped_data[transmitter_id] = transmitter_data
response_data = {
'count': queryset.count(),
'results': grouped_data
}
return Response(response_data)

635
docs/SyncHadis.md

@ -0,0 +1,635 @@
# Hadis Sync API Endpoints Documentation
This document provides comprehensive examples of all sync endpoints in the Hadis API. These endpoints are designed for offline mobile applications and return complete datasets in optimized formats.
## Overview
The sync endpoints provide complete data synchronization for offline use. They return all data at once (no pagination) and are optimized with `select_related` and `prefetch_related` for performance.
## Base URL
```
https://api.example.com/api/hadis/
```
---
## 1. Sync Sects
**Endpoint:** `GET /sync/sects/`
**Purpose:** Get all active sects grouped by sect type (Shia/Sunni)
### Response Structure
```json
{
"shia": [
{
"id": 1,
"title": "Shia Hadith Collections",
"description": "Primary collections of Shia hadith",
"source_types": ["quran", "hadith"]
}
],
"sunni": [
{
"id": 2,
"title": "Sunni Hadith Collections",
"description": "Primary collections of Sunni hadith",
"source_types": ["hadith"]
}
]
}
```
---
## 2. Sync Categories Tree
**Endpoint:** `GET /sync/categories/tree/`
**Purpose:** Get complete hierarchical category tree grouped by sect type with enhanced child information
### Response Structure
```json
{
"count": 12,
"results": {
"shia": {
"sects": {
"1": {
"id": 1,
"sect_type": "shia",
"title": "Shia Hadith Collections",
"description": "Collections of Shia hadith",
"order": 1
}
},
"categories": {
"quran": [
{
"id": 1,
"name": "Tafsir",
"hadis_count": 150,
"has_hadis": false,
"order": 1,
"xmind_file": "http://example.com/media/xmind/tafsir.xmind",
"has_xmind_file": true,
"children": [
{
"id": 2,
"name": "Surah Al-Fatiha",
"hadis_count": 25,
"has_hadis": true,
"order": 1,
"father_category": {
"id": 1,
"name": "Tafsir",
"sect_id": 1,
"sect_type": "shia",
"source_type": "quran"
},
"hadis_details": [
{
"id": 1,
"title": "The Opening",
"title_narrator": "From Abu Hurairah",
"text": "Actions are but by intention...",
"translation": "Actions are but by intention...",
"share_link": "http://example.com/hadis/1"
},
{
"id": 2,
"title": "Prayer Times",
"title_narrator": "From Abdullah ibn Masud",
"text": "The five daily prayers...",
"translation": "The five daily prayers...",
"share_link": "http://example.com/hadis/2"
}
],
"children": []
},
{
"id": 3,
"name": "Surah Al-Baqarah",
"hadis_count": 125,
"has_hadis": false,
"order": 2,
"father_category": {
"id": 1,
"name": "Tafsir",
"sect_id": 1,
"sect_type": "shia",
"source_type": "quran"
},
"children": [
{
"id": 4,
"name": "Verses 1-50",
"hadis_count": 75,
"has_hadis": true,
"father_category": {
"id": 3,
"name": "Surah Al-Baqarah",
"sect_id": 1,
"sect_type": "shia",
"source_type": "quran"
},
"hadis_details": [
{
"id": 5,
"title": "About Prayer",
"title_narrator": "From Ali ibn Abi Talib",
"text": "Prayer is the pillar of religion...",
"translation": "Prayer is the pillar of religion...",
"share_link": "http://example.com/hadis/5"
}
]
}
]
}
]
}
],
"hadith": []
}
},
"sunni": {
"sects": {
"2": {
"id": 2,
"sect_type": "sunni",
"title": "Sunni Hadith Collections",
"description": "Collections of Sunni hadith",
"order": 2
}
},
"categories": {
"hadith": [
{
"id": 10,
"name": "Sahih al-Bukhari",
"hadis_count": 2500,
"has_hadis": true,
"hadis_details": [
{
"id": 100,
"title": "The Beginning of Revelation",
"title_narrator": "From Aisha",
"text": "The first revelation came to Prophet Muhammad...",
"translation": "The first revelation came to Prophet Muhammad...",
"share_link": "http://example.com/hadis/100"
},
{
"id": 101,
"title": "Prayer in the Mosque",
"title_narrator": "From Umar ibn Khattab",
"text": "The reward of prayer in congregation...",
"translation": "The reward of prayer in congregation...",
"share_link": "http://example.com/hadis/101"
}
],
"children": []
},
{
"id": 11,
"name": "Sahih Muslim",
"hadis_count": 2200,
"has_hadis": false,
"children": [
{
"id": 12,
"name": "Book of Faith",
"hadis_count": 150,
"has_hadis": true,
"father_category": {
"id": 11,
"name": "Sahih Muslim",
"sect_id": 2,
"sect_type": "sunni",
"source_type": "hadith"
},
"hadis_details": [
{
"id": 200,
"title": "Faith and Actions",
"title_narrator": "From Abu Hurairah",
"text": "Faith consists of more than sixty branches...",
"translation": "Faith consists of more than sixty branches...",
"share_link": "http://example.com/hadis/200"
}
]
}
]
}
]
}
}
}
}
```
---
## 3. Sync Hadis
**Endpoint:** `GET /sync/hadis/`
**Purpose:** Get all hadis data for offline synchronization
### Response Structure
```json
{
"count": 1500,
"results": {
"1": {
"id": 1,
"number": 1,
"category_id": 2,
"title": "The Opening",
"title_narrator": "From Abu Hurairah",
"text": "Actions are but by intention...",
"description": "This hadith emphasizes the importance of intention in all actions...",
"translations": {
"en": "Actions are but by intention...",
"ar": "إنما الأعمال بالنيات...",
"fa": "اعمال به نیت است..."
},
"explanation": "This hadith emphasizes the importance of intention in all actions...",
"address": "Sahih al-Bukhari, Book of Revelation",
"hadis_status": {
"id": 1,
"title": "Sahih",
"color": "green"
},
"hadis_status_text": "Authentic",
"share_link": "http://example.com/hadis/1",
"tags": [
{"id": 1, "title": "Intention"},
{"id": 2, "title": "Actions"}
],
"links": {
"audio": "http://example.com/audio/hadis1.mp3",
"video": "http://example.com/video/hadis1.mp4"
},
"transmitters": [
{
"id": 1,
"order": 1,
"is_gap": false,
"narrator_layer": "sahaba",
"transmitter": {
"id": 1,
"full_name": "Abu Hurairah",
"birth_year_hijri": 18,
"death_year_hijri": 59,
"madhhab": "sunni",
"description": "One of the most prolific narrators of hadith",
"reliability": "very_reliable"
}
}
],
"references": [
{
"id": 1,
"title": "Sahih al-Bukhari",
"images": [
{
"id": 1,
"image": "http://example.com/media/books/bukhari_cover.jpg",
"order": 1,
"description": "Front cover of Sahih al-Bukhari"
}
],
"authors": [
{
"id": 1,
"name": "Muhammad ibn Isma'il al-Bukhari"
}
],
"description": "The most authentic collection of hadith compiled by Imam Bukhari"
}
],
"corrections": [
{
"id": 1,
"title": "Translation Correction",
"description": "Corrected translation for better accuracy",
"translation": {
"en": "Actions are judged by intentions...",
"ar": "إنما الأعمال بالنيات...",
"fa": "اعمال به نیت ها قضاوت می شود..."
}
}
]
},
"2": {
"id": 2,
"number": 2,
"category_id": 3,
"title": "Five Pillars of Islam",
"title_narrator": "From Abdullah ibn Umar",
"text": "Islam is built on five pillars...",
"translations": {
"en": "Islam is built on five pillars...",
"ar": "بني الإسلام على خمس...",
"fa": "اسلام بر پنج پایه استوار است..."
},
"explanation": "This hadith outlines the fundamental practices of Islam...",
"address": "Sahih al-Bukhari, Book of Faith",
"hadis_status": {
"id": 1,
"title": "Sahih",
"color": "green"
},
"hadis_status_text": "Authentic",
"share_link": "http://example.com/hadis/2",
"tags": [
{"id": 3, "title": "Pillars of Islam"},
{"id": 4, "title": "Faith"}
],
"links": {
"audio": "http://example.com/audio/hadis2.mp3"
}
}
}
}
```
---
## 4. Sync Narrators
**Endpoint:** `GET /sync/narrators/`
**Purpose:** Get all transmitter (narrator) data with biographical information and scholarly opinions
### Response Structure
```json
{
"count": 200,
"results": {
"1": {
"id": 1,
"full_name": "Abu Daud Sulaiman ibn al-Ash'ath al-Azdi al-Sijistani",
"biographical": {
"personal_info": {
"full_name": "Abu Daud Sulaiman ibn al-Ash'ath al-Azdi al-Sijistani",
"kunya": "Abu Daud",
"known_as": "Imam Abu Daud",
"nickname": "Al-Sijistani"
},
"dates": {
"birth_year_hijri": 202,
"death_year_hijri": 275,
"age_at_death": 73
},
"locations": {
"origin": "Sijistan (modern Sistan)",
"lived_in": "Basra, Baghdad",
"died_in": "Basra"
},
"religious_profile": {
"reliability": "very_reliable",
"madhhab": "shafii",
"in_sahih_muslim": true,
"in_sahih_bukhari": false
},
"description": "One of the six canonical hadith collectors. Known for his compilation 'Sunan Abu Daud'.",
"thumbnail": "http://example.com/media/transmitters/abu_daud.jpg"
},
"scholars_opinions": [
{
"id": 1,
"scholar_name": "Imam al-Nawawi",
"opinion_text": "Abu Daud is reliable and trustworthy in his transmissions. His collection is one of the six authentic books.",
"status": "confirmed",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
},
{
"id": 2,
"scholar_name": "Ibn Kathir",
"opinion_text": "Abu Daud was meticulous in his research and only included authentic hadith in his collection.",
"status": "confirmed",
"created_at": "2024-01-16T14:20:00Z",
"updated_at": "2024-01-16T14:20:00Z"
}
]
},
"2": {
"id": 2,
"full_name": "Muhammad ibn Isma'il al-Bukhari",
"biographical": {
"personal_info": {
"full_name": "Muhammad ibn Isma'il al-Bukhari",
"kunya": "Abu Abdullah",
"known_as": "Imam al-Bukhari",
"nickname": "The Collector"
},
"dates": {
"birth_year_hijri": 194,
"death_year_hijri": 256,
"age_at_death": 62
},
"locations": {
"origin": "Bukhara (modern Uzbekistan)",
"lived_in": "Bukhara, Nishapur, Baghdad",
"died_in": "Khartank, near Bukhara"
},
"religious_profile": {
"reliability": "very_reliable",
"madhhab": "hanafi",
"in_sahih_muslim": true,
"in_sahih_bukhari": true
},
"description": "The compiler of Sahih al-Bukhari, considered the most authentic hadith collection by Muslims.",
"thumbnail": "http://example.com/media/transmitters/bukhari.jpg"
},
"scholars_opinions": [
{
"id": 3,
"scholar_name": "Imam Muslim",
"opinion_text": "Al-Bukhari is the most knowledgeable person regarding the conditions of narrators and the defects of hadith.",
"status": "confirmed",
"created_at": "2024-01-17T09:15:00Z",
"updated_at": "2024-01-17T09:15:00Z"
},
{
"id": 4,
"scholar_name": "Ibn Hajar al-Asqalani",
"opinion_text": "The hadith of al-Bukhari are the most authentic after the Quran.",
"status": "confirmed",
"created_at": "2024-01-18T11:45:00Z",
"updated_at": "2024-01-18T11:45:00Z"
}
]
}
}
}
```
---
## 5. Sync References
**Endpoint:** `GET /sync/references/`
**Purpose:** Get all book reference data with basic information, detailed publication info, and related hadises
### Response Structure
```json
{
"count": 50,
"results": {
"1": {
"id": 1,
"title": "Sahih al-Bukhari",
"basic_info": {
"title": "Sahih al-Bukhari",
"authors": [
{
"id": 1,
"name": "Muhammad ibn Isma'il al-Bukhari"
}
],
"rating": 5.0,
"description": "The most authentic collection of hadith compiled by Imam Bukhari. Contains over 7000 hadith with complete chains of narration.",
"volume": "9 volumes"
},
"information": {
"language": "Arabic",
"isbn": "978-1234567890",
"year_of_publication": "846",
"number_of_pages": 4200,
"volume_info": "9 volumes",
"rating": 5.0
},
"hadis": [
{
"id": 1,
"title": "The Opening",
"title_narrator": "From Abu Hurairah",
"text": "Actions are but by intention...",
"translation": "Actions are but by intention...",
"share_link": "http://example.com/hadis/1"
},
{
"id": 2,
"title": "Five Pillars of Islam",
"title_narrator": "From Abdullah ibn Umar",
"text": "Islam is built on five pillars...",
"translation": "Islam is built on five pillars...",
"share_link": "http://example.com/hadis/2"
},
{
"id": 100,
"title": "The Beginning of Revelation",
"title_narrator": "From Aisha",
"text": "The first revelation came to Prophet Muhammad...",
"translation": "The first revelation came to Prophet Muhammad...",
"share_link": "http://example.com/hadis/100"
}
]
},
"2": {
"id": 2,
"title": "Sahih Muslim",
"basic_info": {
"title": "Sahih Muslim",
"authors": [
{
"id": 2,
"name": "Muslim ibn al-Hajjaj al-Naysaburi"
}
],
"rating": 4.9,
"description": "Second most authentic hadith collection, compiled by Imam Muslim. Known for its strict criteria for authenticity.",
"volume": "8 volumes"
},
"information": {
"language": "Arabic",
"isbn": "978-0987654321",
"year_of_publication": "875",
"number_of_pages": 3800,
"volume_info": "8 volumes",
"rating": 4.9
},
"hadis": [
{
"id": 3,
"title": "Faith and Actions",
"title_narrator": "From Abu Hurairah",
"text": "Faith consists of more than sixty branches...",
"translation": "Faith consists of more than sixty branches...",
"share_link": "http://example.com/hadis/3"
},
{
"id": 4,
"title": "Purification",
"title_narrator": "From Abu Hurairah",
"text": "The key to prayer is purification...",
"translation": "The key to prayer is purification...",
"share_link": "http://example.com/hadis/4"
}
]
},
"3": {
"id": 3,
"title": "Tafsir Ibn Kathir",
"basic_info": {
"title": "Tafsir Ibn Kathir",
"authors": [
{
"id": 3,
"name": "Ibn Kathir"
}
],
"rating": 4.8,
"description": "Comprehensive tafsir (exegesis) of the Quran, combining hadith and scholarly opinions.",
"volume": "4 volumes"
},
"information": {
"language": "Arabic",
"isbn": "978-1122334455",
"year_of_publication": "1370",
"number_of_pages": 2800,
"volume_info": "4 volumes",
"rating": 4.8
},
"hadis": [
{
"id": 5,
"title": "Quranic Interpretation",
"title_narrator": "From Ibn Abbas",
"text": "The Quran should be interpreted in light of the Prophet's explanations...",
"translation": "The Quran should be interpreted in light of the Prophet's explanations...",
"share_link": "http://example.com/hadis/5"
}
]
}
}
}
```
---
## Usage Notes
### **Performance Optimizations**
- All sync endpoints use `NoPagination` for complete dataset retrieval
- Database queries are optimized with `select_related` and `prefetch_related`
- Related data is prefetched to avoid N+1 query problems
### **Data Relationships**
- **Categories Tree**: Hierarchical structure with father category references and embedded hadis details
- **Hadis**: Include full translation dictionaries and metadata
- **Narrators**: Biographical data grouped with scholarly opinions
- **References**: Publication details with embedded related hadis
### **Offline Synchronization**
- Designed for mobile apps requiring complete offline datasets
- Structured for efficient client-side caching and updates
- Includes all necessary related data to minimize API calls
### **Response Format**
All sync endpoints return:
```json
{
"count": <total_records>,
"results": {
"<id>": { ...record_data... }
}
}
```
This format allows for easy lookup by ID and provides total count information.

130
docs/hadisdetail.md

@ -0,0 +1,130 @@
```json
{
"id": 1800,
"number": 1,
"title": "Достоинство молитвы и ее место в религии - Толкование суры Аль-Фатиха (1)",
"title_narrator": null,
"text": "قال رسول الله صلى الله عليه وآله: الصلاة عمود الدين، إن قبلت قبل ما سواها، وإن ردت رد ما سواها. وهي أول ما يحاسب عليه العبد يوم القيامة، فإن صلحت صلح سائر عمله، وإن فسدت فسد سائر عمله.\n\nوالصلاة معراج المؤمن، وهي قربان كل تقي، وهي حب الله تعالى. من أحبها وأقامها في أوقاتها وحافظ على حدودها رفعه الله إلى درجة الأبرار. ومن استخف بها وضيعها وتركها فقد استخف بدين الله، ولا نصيب له في الإسلام.\n\nإن الله تعالى فرض خمس صلوات في اليوم والليلة، وجعل لكل صلاة وقتاً معلوماً، فمن صلاها في وقتها وأتم ركوعها وسجودها وخشوعها، كانت له نوراً وبرهاناً ونجاة يوم القيامة.",
"translation": "The Messenger of Allah said: Prayer is the pillar of religion, if it is accepted, other deeds are accepted, and if it is rejected, other deeds are rejected. It is the first thing for which a servant will be held accountable on the Day of Judgment, and if it is sound, all his other deeds will be sound, and if it is corrupted, all his other deeds will be corrupted.\n\nPrayer is the ascension of the believer, it is the offering of every God-fearing person, and it is the love of Allah the Almighty. Whoever loves it and establishes it at its times and maintains its boundaries, Allah will raise him to the rank of the righteous. And whoever takes it lightly, wastes it and abandons it, has taken Allah's religion lightly, and has no share in Islam.\n\nIndeed, Allah the Almighty has prescribed five prayers in a day and night, and has appointed a specific time for each prayer. Whoever prays them at their time and completes their bowing, prostration and humility, they will be light, proof and salvation for him on the Day of Judgment.",
"explanation": "Этот обширный хадис представляет собой фундаментальное учение о молитве в Исламе. Он раскрывает несколько ключевых аспектов:\n\nВо-первых, молитва описывается как \"столп религии\" (عمود الدين), что указывает на ее центральную роль в исламской вере. Это метафора подчеркивает, что как здание не может стоять без столпов, так и религиозная жизнь мусульманина не может быть полноценной без молитвы.\n\nВо-вторых, хадис устанавливает принцип, согласно которому принятие или отвержение молитвы Аллахом определяет судьбу всех остальных деяний верующего. Это подчеркивает качественный аспект молитвы - важна не только ее форма, но и искренность, концентрация и правильное выполнение.\n\nВ-третьих, молитва представлена как \"معراج المؤمن\" (вознесение верующего), что отсылает к ночному путешествию Пророка (мир ему) и подчеркивает духовное измерение молитвы как средства приближения к Всевышнему.\n\nХадис также подчеркивает важность своевременного совершения молитв и соблюдения их внешних и внутренних условий, обещая великую награду тем, кто относится к молитве с должным вниманием и уважением.",
"address": null,
"hadis_status_text": null,
"links": [
{
"link": "https://example.com/source1",
"title": "Source 1"
},
{
"link": "https://example.com/source2",
"title": "Source 2"
}
],
"share_link": "https://imamjavad.nwhco.ir/hadis/None",
"status": true,
"category": {
"id": 330,
"title": "Толкование суры Аль-Фатиха",
"category_type": null
},
"hadis_status": {
"id": 130,
"title": "Прерванный",
"color": "orange"
},
"tags": [
{
"id": 510,
"title": "Хадж"
},
{
"id": 514,
"title": "Терпение"
},
{
"id": 520,
"title": "Постановления"
}
],
"transmitters": [
{
"id": 5992,
"transmitter": {
"id": 53,
"full_name": "Мухаммад ибн аль-Хасан ат-Туси",
"birth_year_hijri": 385,
"death_year_hijri": 460,
"description": "Шейх Туси, автор книг Тахзиб аль-Ахкам и аль-Истибсар",
"reliability": "unknown",
"madhhab": "unknown"
},
"order": 1,
"is_gap": false
},
{
"id": 5993,
"transmitter": {
"id": 60,
"full_name": "Мухаммад ибн Муслим",
"birth_year_hijri": 70,
"death_year_hijri": 150,
"description": "Мухаммад ибн Муслим, из сподвижников имама Бакира и имама Садика (мир им)",
"reliability": "unknown",
"madhhab": "unknown"
},
"order": 2,
"is_gap": false
},
{
"id": 5994,
"transmitter": {
"id": 56,
"full_name": "Абу Дауд ас-Сиджистани",
"birth_year_hijri": 202,
"death_year_hijri": 275,
"description": "Имам Абу Дауд, автор Сунан Абу Дауд",
"reliability": "unknown",
"madhhab": "unknown"
},
"order": 3,
"is_gap": false
},
{
"id": 5995,
"transmitter": {
"id": 59,
"full_name": "Али ибн аль-Хусейн ас-Саджжад",
"birth_year_hijri": 38,
"death_year_hijri": 95,
"description": "Имам Али ибн аль-Хусейн (мир ему), четвертый имам шиитов",
"reliability": "unknown",
"madhhab": "unknown"
},
"order": 4,
"is_gap": true
},
{
"id": 5996,
"transmitter": {
"id": 58,
"full_name": "Мухаммад ибн Али аль-Бакир",
"birth_year_hijri": 57,
"death_year_hijri": 114,
"description": "Имам Мухаммад Бакир (мир ему), пятый имам шиитов",
"reliability": "unknown",
"madhhab": "unknown"
},
"order": 5,
"is_gap": false
}
],
"description": null,
"references": [
{
"id": 2193,
"book_title": null,
"book_images": null,
"book_authors": null
}
]
}
```
Loading…
Cancel
Save