5 Commits
2c6e8ad8cc
...
354a64c742
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
354a64c742 |
feat(hadis): add single-file sqlite export and optimize sync serializers
- Optimize HadisSyncSerializer: remove unused number, address_details, and book descriptions - Separate sync serializers for corrections and interpretations (omitting redundant hadis_info and category_info) - Add HadisDatabaseVersion model and migration for tracking offline SQLite DB - Add export_hadis_sqlite management command with gzip compression and single-file overwrite - Add GET /api/hadis/sync/database/ endpoint and enhance version serializers - Automatically trigger background SQLite database export on version increment in admin |
1 month ago |
|
|
315fc26cad |
merged with recent changes
|
1 month ago |
|
|
b2e6469b13 |
sync request increment support enhancement
|
1 month ago |
|
|
6ac32e11a2 |
perf(db): resolve N+1 queries across endpoints and optimize gunicorn concurrency
- Add request-level user bookmark memoization in BookmarkStatusSerializer to eliminate redundant queries across all lists - Optimize BookReferenceSyncView and BookReference.authors caching (reduced queries from 185 to 10) - Add multi-level prefetch_related for references and images in HadisMainListView (reduced queries from 109 to 6) - Add incremental sync support (updated_after/since) in HadisSyncView - Add select_related for language in BookListView (reduced queries from 35 to 18) - Annotate episode count and cache effective_thumbnail in podcast and video playlist views (reduced queries from 22/17 to 4) - Prefetch categories with annotated article counts in ArticleListAPIView (reduced queries from 41 to 3) - Scale Gunicorn workers/threads to 4w/4t (16 concurrency) with gthread in docker-compose.prod.yml |
1 month ago |
|
|
a90852f8c7 |
feat(video): temporarily disable youtube stream url resolution
|
1 month ago |
26 changed files with 3218 additions and 1370 deletions
-
2apps/article/serializers.py
-
15apps/article/views.py
-
13apps/bookmark/serializers/bookmark.py
-
492apps/hadis/HADIS_SYNC_SAMPLE.md
-
21apps/hadis/admin/version.py
-
689apps/hadis/hadis_sample.json
-
415apps/hadis/management/commands/export_hadis_sqlite.py
-
34apps/hadis/migrations/0040_hadisdatabaseversion.py
-
21apps/hadis/models/reference.py
-
28apps/hadis/models/version.py
-
35apps/hadis/serializers/hadis.py
-
6apps/hadis/serializers/reference.py
-
42apps/hadis/serializers/version.py
-
3apps/hadis/urls.py
-
25apps/hadis/views/hadis.py
-
2apps/hadis/views/reference.py
-
25apps/hadis/views/version.py
-
25apps/hadis/views_admin.py
-
2apps/library/views.py
-
10apps/podcast/models.py
-
2apps/podcast/serializers.py
-
10apps/podcast/views.py
-
10apps/video/models.py
-
2apps/video/views.py
-
2docker-compose.prod.yml
-
91utils/youtube.py
@ -0,0 +1,492 @@ |
|||
# نمونه کامل خروجی یک آبجکت حدیث در اندپوینت سینک (`/api/hadis/sync/hadis/`) |
|||
|
|||
این سند ساختار دقیق، واقعی و تودرتوی **فقط یک رکورد حدیث** (حدیث شماره ۱) را نشان میدهد که مستقیماً از دیتابیس فعلی و از طریق سریالایزر `HadisSyncSerializer` استخراج شده است. |
|||
|
|||
--- |
|||
|
|||
## 📊 مشخصات این آبجکت: |
|||
- **تعداد خطوط JSON برای یک حدیث:** ۶۸۹ خط! |
|||
- **حجم خالص متنی برای یک حدیث:** حدود **۳۲ کیلوبایت** |
|||
- **حجم کل برای ۱۰۵۳ حدیث:** حدود **۳۳ مگابایت** (به دلیل تکرار دادههای تودرتو) |
|||
|
|||
--- |
|||
|
|||
## 🔍 نقاط بحرانی تکرار و تودرتو بودن (Redundancy & Bloat): |
|||
|
|||
1. **تکرار تفاسیر دستهبندی در هر حدیث (`interpretations`):** |
|||
- تفاسیر به دستهبندی تعلق دارند، اما در خروجی **داخل تکتک احادیث آن دسته تکرار میشوند**. متون تفاسیر شامل کدهای طولانی HTML عربی و روسی هستند. |
|||
2. **تکرار مشخصات راویان و لایهها (`transmitters`):** |
|||
- برای هر راوی در زنجیره سند (مثلاً ۱۰ راوی)، آبجکتهای کامل `reliability` و `layer_name` و `layer_description` به همراه لیستی از `uncertain_transmitters` تکرار میشوند. |
|||
3. **تکرار اطلاعات کتابها و رفرنسها در تصحیحات (`corrections -> references`):** |
|||
- داخل هر تصحیح، آبجکتهای رفرنس، تصاویر، مشخصات چاپ (`edition_info`) و لینکها به صورت تودرتو دوباره تکرار شدهاند. |
|||
4. **ارجاع به خودِ حدیث در بخش تصحیحات (`hadis_info`):** |
|||
- داخل آرایه تصحیحاتِ همین حدیث، فیلد `hadis_info` دوباره `id` و `slug` خودِ همین حدیث را تکرار میکند! |
|||
|
|||
--- |
|||
|
|||
## 📄 ساختار کامل JSON (نمونه واقعی استخراجشده از دیتابیس): |
|||
|
|||
```json |
|||
{ |
|||
"id": 1891, |
|||
"number": 1, |
|||
"slug": "the-merit-of-seeking-knowledge", |
|||
"category_id": 1036, |
|||
"category_slug": "reflections", |
|||
"title": "The Merit of Seeking Knowledge", |
|||
"title_narrator": "Jabir bin Abdullah", |
|||
"text": "اتَّقِ اللَّهَ حَيْثُمَا كُنْتَ، وَأَتْبِعِ السَّيِّئَةَ الْحَسَنَةَ تَمْحُهَا.", |
|||
"translation": [ |
|||
{ |
|||
"title": "Передается от Пророка (мир ему): Правда ведет к благочестию. Это путь праведных.", |
|||
"language_code": "ru" |
|||
}, |
|||
{ |
|||
"title": "The best among you are those who have the best manners and character.", |
|||
"language_code": "en" |
|||
} |
|||
], |
|||
"detail": { |
|||
"address": [ |
|||
"Sahih al-Bukhari", |
|||
"Book of Revelation", |
|||
"Chapter 1: How Revelation Began" |
|||
], |
|||
"address_details": [], |
|||
"hadis_status": { |
|||
"id": 133, |
|||
"title": "Authentic / Accepted", |
|||
"description": "A Sahih (Authentic) Hadith represents the highest level of reliability. It possesses a continuous chain of narrators (Isnad) made up of upright (Adl) and retentive (Dabit) transmitters, free from any hidden defects (Illah) or irregularities (Shudhudh). It is universally accepted for deriving Islamic laws.", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
}, |
|||
"status_text": null, |
|||
"share_link": "https://dovodi.newhorizonco.uk/arguments/hadith/hadis-ru-1-7c2df773", |
|||
"links": { |
|||
"Dorar": "https://dorar.net/hadith/1804", |
|||
"Al-Islam": "https://www.al-islam.org/6596", |
|||
"IslamWeb": "https://www.islamweb.net/ar/fatwa/6463", |
|||
"Sunnah.com": "https://sunnah.com/bukhari/3147", |
|||
"IslamicFinder": "https://www.islamicfinder.org/1779" |
|||
}, |
|||
"tags": [ |
|||
{ |
|||
"id": 510, |
|||
"title": "Хадж" |
|||
}, |
|||
{ |
|||
"id": 516, |
|||
"title": "Доверие" |
|||
}, |
|||
{ |
|||
"id": 561, |
|||
"title": "Kindness" |
|||
}, |
|||
{ |
|||
"id": 565, |
|||
"title": "Hellfire (Jahannam)" |
|||
}, |
|||
{ |
|||
"id": 567, |
|||
"title": "Marriage (Nikah)" |
|||
} |
|||
], |
|||
"references": [ |
|||
{ |
|||
"id": 2538, |
|||
"title": "Man La Yahduruhu al-Faqih", |
|||
"authors": [ |
|||
{ |
|||
"id": 9, |
|||
"name": "sheykh hamid" |
|||
} |
|||
], |
|||
"description": [ |
|||
{ |
|||
"title": "For him who is not in the presence of a jurisprudent - Shia collection.", |
|||
"language_code": "en" |
|||
}, |
|||
{ |
|||
"title": "توضیحات درباره من لا یحضره الفقیه", |
|||
"language_code": "fa" |
|||
} |
|||
], |
|||
"share_link": "https://dovodi.newhorizonco.uk/arguments/sources/man-la-yahduruhu-al-faqih" |
|||
} |
|||
], |
|||
"reference_images": [ |
|||
{ |
|||
"id": 2541, |
|||
"thumbnail": "https://dovodi.newhorizonco.uk/media/hadis/reference_images/1891_ref1.png", |
|||
"priority": 1 |
|||
}, |
|||
{ |
|||
"id": 2542, |
|||
"thumbnail": "https://dovodi.newhorizonco.uk/media/hadis/reference_images/1891_ref2.png", |
|||
"priority": 2 |
|||
}, |
|||
{ |
|||
"id": 2543, |
|||
"thumbnail": "https://dovodi.newhorizonco.uk/media/hadis/reference_images/1891_ref3.png", |
|||
"priority": 3 |
|||
}, |
|||
{ |
|||
"id": 2544, |
|||
"thumbnail": "https://dovodi.newhorizonco.uk/media/hadis/reference_images/1891_ref4.png", |
|||
"priority": 4 |
|||
} |
|||
] |
|||
}, |
|||
"narrators": { |
|||
"description": "Focuses on the relationship between the Creator and the creation.", |
|||
"transmitters": [ |
|||
{ |
|||
"id": 850, |
|||
"name": "Ali ibn Yaqtin", |
|||
"slug": "ali-ibn-yaqtin", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 14, |
|||
"title": "Reliable", |
|||
"slug": "reliable-1-190858903395", |
|||
"color": "blue", |
|||
"main_color_code": "#5172E1" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": true, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "40", |
|||
"order": 0 |
|||
}, |
|||
{ |
|||
"id": 859, |
|||
"name": "Al-Muhaqqiq al-Hilli (Ja'far ibn al-Hasan)", |
|||
"slug": "al-muhaqqiq-al-hilli-jafar-ibn-al-hasan", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 17, |
|||
"title": "Very Weak", |
|||
"slug": "very-weak-1-190858905701", |
|||
"color": "red", |
|||
"main_color_code": "#D33A3A" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": false, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "36", |
|||
"order": 1 |
|||
}, |
|||
{ |
|||
"id": 867, |
|||
"name": "Al-Miqdad ibn al-Aswad", |
|||
"slug": "al-miqdad-ibn-al-aswad", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 12, |
|||
"title": "Unknown", |
|||
"slug": "unknown", |
|||
"color": "gray", |
|||
"main_color_code": "#374151" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": true, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "117", |
|||
"order": 2 |
|||
}, |
|||
{ |
|||
"id": 1016, |
|||
"name": "Muhammad ibn Yahya al-Attar al-Qummi", |
|||
"slug": "muhammad-ibn-yahya-al-attar-al-qummi", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 58, |
|||
"title": "сподвижник", |
|||
"slug": "сподвижник", |
|||
"color": "gray", |
|||
"main_color_code": "#374151" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": false, |
|||
"is_uncertain": true, |
|||
"uncertain_transmitters": [ |
|||
{ |
|||
"id": 871, |
|||
"name": "Malik al-Ashtar al-Nakha'i", |
|||
"slug": "malik-al-ashtar-al-nakhai", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "161", |
|||
"reliability": { |
|||
"id": 7, |
|||
"title": "Very Reliable", |
|||
"slug": "very-reliable", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
} |
|||
}, |
|||
{ |
|||
"id": 1016, |
|||
"name": "Muhammad ibn Yahya al-Attar al-Qummi", |
|||
"slug": "muhammad-ibn-yahya-al-attar-al-qummi", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": "", |
|||
"death_year_hijri": "57", |
|||
"reliability": { |
|||
"id": 58, |
|||
"title": "сподвижник", |
|||
"slug": "сподвижник", |
|||
"color": "gray", |
|||
"main_color_code": "#374151" |
|||
} |
|||
} |
|||
], |
|||
"birth_year_hijri": "", |
|||
"death_year_hijri": "57", |
|||
"order": 3 |
|||
}, |
|||
{ |
|||
"id": 886, |
|||
"name": "Ali ibn Mahziyar al-Ahwazi", |
|||
"slug": "ali-ibn-mahziyar-al-ahwazi", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 16, |
|||
"title": "Weak", |
|||
"slug": "weak-1-190858898727", |
|||
"color": "orange", |
|||
"main_color_code": "#E67E22" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": false, |
|||
"is_uncertain": true, |
|||
"uncertain_transmitters": [ |
|||
{ |
|||
"id": 884, |
|||
"name": "Abd Allah ibn Mughirah", |
|||
"slug": "abd-allah-ibn-mughirah", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "385", |
|||
"reliability": { |
|||
"id": 13, |
|||
"title": "Very Reliable", |
|||
"slug": "very-reliable-1-190858893632", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
} |
|||
}, |
|||
{ |
|||
"id": 886, |
|||
"name": "Ali ibn Mahziyar al-Ahwazi", |
|||
"slug": "ali-ibn-mahziyar-al-ahwazi", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "405", |
|||
"reliability": { |
|||
"id": 16, |
|||
"title": "Weak", |
|||
"slug": "weak-1-190858898727", |
|||
"color": "orange", |
|||
"main_color_code": "#E67E22" |
|||
} |
|||
} |
|||
], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "405", |
|||
"order": 4 |
|||
}, |
|||
{ |
|||
"id": 1033, |
|||
"name": "Muhammad Hasan al-Shirazi", |
|||
"slug": "muhammad-hasan-al-shirazi", |
|||
"known_as": "زراره", |
|||
"nickname": "زراره شیبانی", |
|||
"reliability": { |
|||
"id": 7, |
|||
"title": "Very Reliable", |
|||
"slug": "very-reliable", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
}, |
|||
"layer_id": 5700, |
|||
"narrator_layer_id": 5700, |
|||
"layer_level": 2, |
|||
"layer_name": "Prominent Hadith Compilers", |
|||
"layer_description": "Leading scholars, authors, and systematizers of prophetic narrations.", |
|||
"is_gap": false, |
|||
"is_uncertain": true, |
|||
"uncertain_transmitters": [ |
|||
{ |
|||
"id": 1033, |
|||
"name": "Muhammad Hasan al-Shirazi", |
|||
"slug": "muhammad-hasan-al-shirazi", |
|||
"known_as": "زراره", |
|||
"nickname": "زراره شیبانی", |
|||
"birth_year_hijri": "80", |
|||
"death_year_hijri": "150", |
|||
"reliability": { |
|||
"id": 7, |
|||
"title": "Very Reliable", |
|||
"slug": "very-reliable", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
} |
|||
}, |
|||
{ |
|||
"id": 853, |
|||
"name": "Muhammad ibn Ya'qub al-Kulayni", |
|||
"slug": "muhammad-ibn-yaqub-al-kulayni", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "35", |
|||
"reliability": { |
|||
"id": 15, |
|||
"title": "Acceptable", |
|||
"slug": "acceptable-1-190858896271", |
|||
"color": "yellow", |
|||
"main_color_code": "#EDC130" |
|||
} |
|||
} |
|||
], |
|||
"birth_year_hijri": "80", |
|||
"death_year_hijri": "150", |
|||
"order": 5 |
|||
} |
|||
] |
|||
}, |
|||
"explanations": [ |
|||
{ |
|||
"title": "Vocabulary & Linguistic Analysis", |
|||
"detail": "The term 'Niyyah' (Intention) is pivotal in Islamic lexicon, derived from the root 'nawa'..." |
|||
}, |
|||
{ |
|||
"title": "Context of Revelation (Asbab al-Wurud)", |
|||
"detail": "This tradition is famously known as the 'Hadith of the Migrant to Umm Qais'..." |
|||
} |
|||
], |
|||
"corrections": [ |
|||
{ |
|||
"id": 26, |
|||
"title": "Scholar Note #4", |
|||
"slug": "scholar-note-4", |
|||
"narrator": "زُرارَةُ بْنُ أَعْيَنَ الشَّيبانِيّ", |
|||
"description": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ\nالْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ...", |
|||
"translation": "Revised text segment for correction 4...", |
|||
"share_link": "https://dovodi.newhorizonco.uk/arguments/hadith/hadis-ru-1-7c2df773/corrections/scholar-note-4", |
|||
"hadis_info": { |
|||
"id": 1891, |
|||
"number": 1, |
|||
"slug": "the-merit-of-seeking-knowledge" |
|||
}, |
|||
"address": [ |
|||
"Tirmidhi, Abu Isa Muhammad ibn Isa (died 279 AH), \"Jami' al-Sahih (Sunan At-Tirmidhi)\"..." |
|||
], |
|||
"images": [], |
|||
"references": [ |
|||
{ |
|||
"id": 4034, |
|||
"book": null, |
|||
"author": null, |
|||
"edition": null, |
|||
"volume_info": null, |
|||
"hadith_number": null, |
|||
"volume": null, |
|||
"pages": null, |
|||
"address": "Tirmidhi, Abu Isa Muhammad ibn Isa...", |
|||
"url": null, |
|||
"open_book_url": null, |
|||
"citation_summary": "", |
|||
"images": [], |
|||
"images_count": 0, |
|||
"book_title": null, |
|||
"book_authors": [], |
|||
"edition_info": null |
|||
} |
|||
], |
|||
"links": [ |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка" |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"interpretations": [ |
|||
{ |
|||
"id": 12, |
|||
"title": null, |
|||
"slug": "cat-l3-25-7f5bcb", |
|||
"narrator": "زُرارَةُ بْنُ أَعْيَنَ الشَّيبانِيّ", |
|||
"text": "<p dir=\"rtl\">الْمَسْأَلَةُ الثَّامِنَةُ : قَوْلُهُ : { أَهْلَ الْبَيْتِ }...</p>", |
|||
"translation": "<p>Вопрос восьмой: (что означают) слова: Ахл аль-бейт...</p>", |
|||
"category_info": { |
|||
"id": 1036, |
|||
"slug": "reflections", |
|||
"title": "Reflections" |
|||
}, |
|||
"address": [ |
|||
"Tirmidhi, Abu Isa Muhammad ibn Isa..." |
|||
], |
|||
"images": [], |
|||
"links": [], |
|||
"references": [ |
|||
{ |
|||
"id": 76, |
|||
"book_title": "last book", |
|||
"book_authors": [ |
|||
{ |
|||
"id": 9, |
|||
"name": "sheykh hamid" |
|||
} |
|||
], |
|||
"edition_info": null, |
|||
"volume_info": null, |
|||
"hadith_number": null, |
|||
"volume": "", |
|||
"pages": "", |
|||
"address": "Tirmidhi, Abu Isa Muhammad ibn Isa...", |
|||
"url": null, |
|||
"images": [] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
``` |
|||
@ -0,0 +1,689 @@ |
|||
{ |
|||
"id": 1891, |
|||
"number": 1, |
|||
"slug": "the-merit-of-seeking-knowledge", |
|||
"category_id": 1036, |
|||
"category_slug": "reflections", |
|||
"title": "The Merit of Seeking Knowledge", |
|||
"title_narrator": "Jabir bin Abdullah", |
|||
"text": "اتَّقِ اللَّهَ حَيْثُمَا كُنْتَ، وَأَتْبِعِ السَّيِّئَةَ الْحَسَنَةَ تَمْحُهَا.", |
|||
"translation": [ |
|||
{ |
|||
"title": "Передается от Пророка (мир ему): Правда ведет к благочестию. Это путь праведных.", |
|||
"language_code": "ru" |
|||
}, |
|||
{ |
|||
"title": "The best among you are those who have the best manners and character.", |
|||
"language_code": "en" |
|||
} |
|||
], |
|||
"detail": { |
|||
"address": [ |
|||
"Sahih al-Bukhari", |
|||
"Book of Revelation", |
|||
"Chapter 1: How Revelation Began" |
|||
], |
|||
"address_details": [], |
|||
"hadis_status": { |
|||
"id": 133, |
|||
"title": "Authentic / Accepted", |
|||
"description": "A Sahih (Authentic) Hadith represents the highest level of reliability. It possesses a continuous chain of narrators (Isnad) made up of upright (Adl) and retentive (Dabit) transmitters, free from any hidden defects (Illah) or irregularities (Shudhudh). It is universally accepted for deriving Islamic laws.", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
}, |
|||
"status_text": null, |
|||
"share_link": "https://dovodi.newhorizonco.uk/arguments/hadith/hadis-ru-1-7c2df773", |
|||
"links": { |
|||
"Dorar": "https://dorar.net/hadith/1804", |
|||
"Al-Islam": "https://www.al-islam.org/6596", |
|||
"IslamWeb": "https://www.islamweb.net/ar/fatwa/6463", |
|||
"Sunnah.com": "https://sunnah.com/bukhari/3147", |
|||
"IslamicFinder": "https://www.islamicfinder.org/1779" |
|||
}, |
|||
"tags": [ |
|||
{ |
|||
"id": 510, |
|||
"title": "Хадж" |
|||
}, |
|||
{ |
|||
"id": 516, |
|||
"title": "Доверие" |
|||
}, |
|||
{ |
|||
"id": 561, |
|||
"title": "Kindness" |
|||
}, |
|||
{ |
|||
"id": 565, |
|||
"title": "Hellfire (Jahannam)" |
|||
}, |
|||
{ |
|||
"id": 567, |
|||
"title": "Marriage (Nikah)" |
|||
} |
|||
], |
|||
"references": [ |
|||
{ |
|||
"id": 2538, |
|||
"title": "Man La Yahduruhu al-Faqih", |
|||
"authors": [ |
|||
{ |
|||
"id": 9, |
|||
"name": "sheykh hamid" |
|||
} |
|||
], |
|||
"description": [ |
|||
{ |
|||
"title": "For him who is not in the presence of a jurisprudent - Shia collection.", |
|||
"language_code": "en" |
|||
}, |
|||
{ |
|||
"title": "توضیحات درباره من لا یحضره الفقیه", |
|||
"language_code": "fa" |
|||
} |
|||
], |
|||
"share_link": "https://dovodi.newhorizonco.uk/arguments/sources/man-la-yahduruhu-al-faqih" |
|||
} |
|||
], |
|||
"reference_images": [ |
|||
{ |
|||
"id": 2541, |
|||
"thumbnail": "https://testserver/media/hadis/reference_images/1891_ref1.png", |
|||
"priority": 1 |
|||
}, |
|||
{ |
|||
"id": 2542, |
|||
"thumbnail": "https://testserver/media/hadis/reference_images/1891_ref2.png", |
|||
"priority": 2 |
|||
}, |
|||
{ |
|||
"id": 2543, |
|||
"thumbnail": "https://testserver/media/hadis/reference_images/1891_ref3.png", |
|||
"priority": 3 |
|||
}, |
|||
{ |
|||
"id": 2544, |
|||
"thumbnail": "https://testserver/media/hadis/reference_images/1891_ref4.png", |
|||
"priority": 4 |
|||
} |
|||
] |
|||
}, |
|||
"narrators": { |
|||
"description": "Focuses on the relationship between the Creator and the creation.", |
|||
"transmitters": [ |
|||
{ |
|||
"id": 850, |
|||
"name": "Ali ibn Yaqtin", |
|||
"slug": "ali-ibn-yaqtin", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 14, |
|||
"title": "Reliable", |
|||
"slug": "reliable-1-190858903395", |
|||
"color": "blue", |
|||
"main_color_code": "#5172E1" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": true, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "40", |
|||
"order": 0 |
|||
}, |
|||
{ |
|||
"id": 859, |
|||
"name": "Al-Muhaqqiq al-Hilli (Ja'far ibn al-Hasan)", |
|||
"slug": "al-muhaqqiq-al-hilli-jafar-ibn-al-hasan", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 17, |
|||
"title": "Very Weak", |
|||
"slug": "very-weak-1-190858905701", |
|||
"color": "red", |
|||
"main_color_code": "#D33A3A" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": false, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "36", |
|||
"order": 1 |
|||
}, |
|||
{ |
|||
"id": 867, |
|||
"name": "Al-Miqdad ibn al-Aswad", |
|||
"slug": "al-miqdad-ibn-al-aswad", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 12, |
|||
"title": "Unknown", |
|||
"slug": "unknown", |
|||
"color": "gray", |
|||
"main_color_code": "#374151" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": true, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "117", |
|||
"order": 2 |
|||
}, |
|||
{ |
|||
"id": 1016, |
|||
"name": "Muhammad ibn Yahya al-Attar al-Qummi", |
|||
"slug": "muhammad-ibn-yahya-al-attar-al-qummi", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 58, |
|||
"title": "сподвижник", |
|||
"slug": "сподвижник", |
|||
"color": "gray", |
|||
"main_color_code": "#374151" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": false, |
|||
"is_uncertain": true, |
|||
"uncertain_transmitters": [ |
|||
{ |
|||
"id": 871, |
|||
"name": "Malik al-Ashtar al-Nakha'i", |
|||
"slug": "malik-al-ashtar-al-nakhai", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "161", |
|||
"reliability": { |
|||
"id": 7, |
|||
"title": "Very Reliable", |
|||
"slug": "very-reliable", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
} |
|||
}, |
|||
{ |
|||
"id": 1016, |
|||
"name": "Muhammad ibn Yahya al-Attar al-Qummi", |
|||
"slug": "muhammad-ibn-yahya-al-attar-al-qummi", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": "", |
|||
"death_year_hijri": "57", |
|||
"reliability": { |
|||
"id": 58, |
|||
"title": "сподвижник", |
|||
"slug": "сподвижник", |
|||
"color": "gray", |
|||
"main_color_code": "#374151" |
|||
} |
|||
} |
|||
], |
|||
"birth_year_hijri": "", |
|||
"death_year_hijri": "57", |
|||
"order": 3 |
|||
}, |
|||
{ |
|||
"id": 886, |
|||
"name": "Ali ibn Mahziyar al-Ahwazi", |
|||
"slug": "ali-ibn-mahziyar-al-ahwazi", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 16, |
|||
"title": "Weak", |
|||
"slug": "weak-1-190858898727", |
|||
"color": "orange", |
|||
"main_color_code": "#E67E22" |
|||
}, |
|||
"layer_id": 5699, |
|||
"narrator_layer_id": 5699, |
|||
"layer_level": 1, |
|||
"layer_name": "Primary Chain & Early Narrators", |
|||
"layer_description": "Early generation transmitters, companions, and direct students.", |
|||
"is_gap": false, |
|||
"is_uncertain": true, |
|||
"uncertain_transmitters": [ |
|||
{ |
|||
"id": 884, |
|||
"name": "Abd Allah ibn Mughirah", |
|||
"slug": "abd-allah-ibn-mughirah", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "385", |
|||
"reliability": { |
|||
"id": 13, |
|||
"title": "Very Reliable", |
|||
"slug": "very-reliable-1-190858893632", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
} |
|||
}, |
|||
{ |
|||
"id": 886, |
|||
"name": "Ali ibn Mahziyar al-Ahwazi", |
|||
"slug": "ali-ibn-mahziyar-al-ahwazi", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "405", |
|||
"reliability": { |
|||
"id": 16, |
|||
"title": "Weak", |
|||
"slug": "weak-1-190858898727", |
|||
"color": "orange", |
|||
"main_color_code": "#E67E22" |
|||
} |
|||
} |
|||
], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "405", |
|||
"order": 4 |
|||
}, |
|||
{ |
|||
"id": 1033, |
|||
"name": "Muhammad Hasan al-Shirazi", |
|||
"slug": "muhammad-hasan-al-shirazi", |
|||
"known_as": "زراره", |
|||
"nickname": "زراره شیبانی", |
|||
"reliability": { |
|||
"id": 7, |
|||
"title": "Very Reliable", |
|||
"slug": "very-reliable", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
}, |
|||
"layer_id": 5700, |
|||
"narrator_layer_id": 5700, |
|||
"layer_level": 2, |
|||
"layer_name": "Prominent Hadith Compilers", |
|||
"layer_description": "Leading scholars, authors, and systematizers of prophetic narrations.", |
|||
"is_gap": false, |
|||
"is_uncertain": true, |
|||
"uncertain_transmitters": [ |
|||
{ |
|||
"id": 1033, |
|||
"name": "Muhammad Hasan al-Shirazi", |
|||
"slug": "muhammad-hasan-al-shirazi", |
|||
"known_as": "زراره", |
|||
"nickname": "زراره شیبانی", |
|||
"birth_year_hijri": "80", |
|||
"death_year_hijri": "150", |
|||
"reliability": { |
|||
"id": 7, |
|||
"title": "Very Reliable", |
|||
"slug": "very-reliable", |
|||
"color": "green", |
|||
"main_color_code": "#1DAC43" |
|||
} |
|||
}, |
|||
{ |
|||
"id": 853, |
|||
"name": "Muhammad ibn Ya'qub al-Kulayni", |
|||
"slug": "muhammad-ibn-yaqub-al-kulayni", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "35", |
|||
"reliability": { |
|||
"id": 15, |
|||
"title": "Acceptable", |
|||
"slug": "acceptable-1-190858896271", |
|||
"color": "yellow", |
|||
"main_color_code": "#EDC130" |
|||
} |
|||
} |
|||
], |
|||
"birth_year_hijri": "80", |
|||
"death_year_hijri": "150", |
|||
"order": 5 |
|||
}, |
|||
{ |
|||
"id": 1016, |
|||
"name": "Muhammad ibn Yahya al-Attar al-Qummi", |
|||
"slug": "muhammad-ibn-yahya-al-attar-al-qummi", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 58, |
|||
"title": "сподвижник", |
|||
"slug": "сподвижник", |
|||
"color": "gray", |
|||
"main_color_code": "#374151" |
|||
}, |
|||
"layer_id": 5700, |
|||
"narrator_layer_id": 5700, |
|||
"layer_level": 2, |
|||
"layer_name": "Prominent Hadith Compilers", |
|||
"layer_description": "Leading scholars, authors, and systematizers of prophetic narrations.", |
|||
"is_gap": true, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": "", |
|||
"death_year_hijri": "57", |
|||
"order": 6 |
|||
}, |
|||
{ |
|||
"id": 856, |
|||
"name": "Ali ibn al-Husayn al-Sharif al-Murtada", |
|||
"slug": "ali-ibn-al-husayn-al-sharif-al-murtada", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 12, |
|||
"title": "Unknown", |
|||
"slug": "unknown", |
|||
"color": "gray", |
|||
"main_color_code": "#374151" |
|||
}, |
|||
"layer_id": 5700, |
|||
"narrator_layer_id": 5700, |
|||
"layer_level": 2, |
|||
"layer_name": "Prominent Hadith Compilers", |
|||
"layer_description": "Leading scholars, authors, and systematizers of prophetic narrations.", |
|||
"is_gap": false, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "37", |
|||
"order": 7 |
|||
}, |
|||
{ |
|||
"id": 89, |
|||
"name": "Al-Fudayl ibn Yasar", |
|||
"slug": "al-fudayl-ibn-yasar", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 9, |
|||
"title": "Acceptable", |
|||
"slug": "acceptable", |
|||
"color": "yellow", |
|||
"main_color_code": "#EDC130" |
|||
}, |
|||
"layer_id": 5700, |
|||
"narrator_layer_id": 5700, |
|||
"layer_level": 2, |
|||
"layer_name": "Prominent Hadith Compilers", |
|||
"layer_description": "Leading scholars, authors, and systematizers of prophetic narrations.", |
|||
"is_gap": false, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "250", |
|||
"order": 8 |
|||
}, |
|||
{ |
|||
"id": 863, |
|||
"name": "Al-Hurr al-Amili (Muhammad ibn al-Hasan)", |
|||
"slug": "al-hurr-al-amili-muhammad-ibn-al-hasan", |
|||
"known_as": "ibn Hilal", |
|||
"nickname": "Al-Basri", |
|||
"reliability": { |
|||
"id": 10, |
|||
"title": "Weak", |
|||
"slug": "weak", |
|||
"color": "orange", |
|||
"main_color_code": "#E67E22" |
|||
}, |
|||
"layer_id": 5700, |
|||
"narrator_layer_id": 5700, |
|||
"layer_level": 2, |
|||
"layer_name": "Prominent Hadith Compilers", |
|||
"layer_description": "Leading scholars, authors, and systematizers of prophetic narrations.", |
|||
"is_gap": true, |
|||
"is_uncertain": false, |
|||
"uncertain_transmitters": [], |
|||
"birth_year_hijri": null, |
|||
"death_year_hijri": "94", |
|||
"order": 9 |
|||
} |
|||
] |
|||
}, |
|||
"explanations": [ |
|||
{ |
|||
"title": "Vocabulary & Linguistic Analysis", |
|||
"detail": "The term 'Niyyah' (Intention) is pivotal in Islamic lexicon, derived from the root 'nawa', meaning to aim, direct, or purpose oneself towards a specific destination. In the terminology of the jurists (Fuqaha), it serves a dual function: firstly, to distinguish acts of worship (Ibadah) from mundane customary habits (Adah)—such as distinguishing the act of washing oneself for cooling off from the act of Ghusl (ritual purification). Secondly, it distinguishes different ranks of worship from one another, such as separating a noon prayer that is obligatory (Fard) from one that is voluntary (Sunnah). Philosophically, scholars like Al-Ghazali have elaborated that Niyyah is the 'spirit' of the action, while the physical movement is merely the 'body'; a body without a spirit is lifeless, just as an action without sincere intention holds no weight in the Divine Court." |
|||
}, |
|||
{ |
|||
"title": "Context of Revelation (Asbab al-Wurud)", |
|||
"detail": "This tradition is famously known as the 'Hadith of the Migrant to Umm Qais'. It was delivered by the Prophet (PBUH) from the pulpit in Medina to address a subtle but critical issue within the community. Reports indicate that a man had migrated from Mecca to Medina not solely for the sake of Allah and His Messenger, but because a woman named Umm Qais had refused to marry him unless he undertook the migration. While his physical journey was identical to the other companions who sacrificed their homes for faith, his internal compass was directed towards a worldly gain. The Prophet (PBUH) used this specific incident to establish a universal maxim: that the validity and reward of any deed are inextricably bound to the hidden motive behind it, warning that one who targets the world will attain only that, with no share in the Hereafter." |
|||
} |
|||
], |
|||
"corrections": [ |
|||
{ |
|||
"id": 26, |
|||
"title": "Scholar Note #4", |
|||
"slug": "scholar-note-4", |
|||
"narrator": "زُرارَةُ بْنُ أَعْيَنَ الشَّيبانِيّ", |
|||
"description": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ\nالْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ، وَالصَّلَاةُ وَالسَّلَامُ عَلَى سَيِّدِنَا مُحَمَّدٍ وَآلِهِ الطَّاهِرِينَ.\nاللَّهُمَّ زَيِّنَّا بِالْعِلْمِ وَالْحِلْمِ، وَاجْعَلْ أَلْسِنَتَنَا ذَاكِرَةً لَكَ وَقُلُوبَنَا خَاشِعَةً لَكَ.\nوَارْزُقْنَا صِدْقَ الْقَوْلِ وَحُسْنَ الْعَمَلِ، إِنَّكَ أَنْتَ الْوَهَّابُ الْكَرِيمُ.", |
|||
"translation": "Revised text segment for correction 4...", |
|||
"share_link": "https://dovodi.newhorizonco.uk/arguments/hadith/hadis-ru-1-7c2df773/corrections/scholar-note-4", |
|||
"hadis_info": { |
|||
"id": 1891, |
|||
"number": 1, |
|||
"slug": "the-merit-of-seeking-knowledge" |
|||
}, |
|||
"address": [ |
|||
"Tirmidhi, Abu Isa Muhammad ibn Isa (died 279 AH), \"Jami' al-Sahih (Sunan At-Tirmidhi)\", book: virtues, chapter: virtues of Ali ibn Abu Talib, volume 5, page 633, hadith 3713, research: Ahmad Muhammad Shakir and others, Mustafa al-Babi al-Halabi Publishing House, Egypt, 2nd edition, 1395 - 1975, in five volumes." |
|||
], |
|||
"images": [], |
|||
"references": [ |
|||
{ |
|||
"id": 4034, |
|||
"book": null, |
|||
"author": null, |
|||
"edition": null, |
|||
"volume_info": null, |
|||
"hadith_number": null, |
|||
"volume": null, |
|||
"pages": null, |
|||
"address": "Tirmidhi, Abu Isa Muhammad ibn Isa (died 279 AH), \"Jami' al-Sahih (Sunan At-Tirmidhi)\", book: virtues, chapter: virtues of Ali ibn Abu Talib, volume 5, page 633, hadith 3713, research: Ahmad Muhammad Shakir and others, Mustafa al-Babi al-Halabi Publishing House, Egypt, 2nd edition, 1395 - 1975, in five volumes.", |
|||
"url": null, |
|||
"open_book_url": null, |
|||
"citation_summary": "", |
|||
"images": [], |
|||
"images_count": 0, |
|||
"book_title": null, |
|||
"book_authors": [], |
|||
"edition_info": null |
|||
} |
|||
], |
|||
"links": [ |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка Первая ссылка ссылкассы..." |
|||
}, |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка." |
|||
}, |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка." |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"id": 25, |
|||
"title": "Alternative Translation #3", |
|||
"slug": "alternative-translation-3", |
|||
"narrator": "زُرارَةُ بْنُ أَعْيَنَ الشَّيبانِيّ", |
|||
"description": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ\nالْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ، وَالصَّلَاةُ وَالسَّلَامُ عَلَى سَيِّدِنَا مُحَمَّدٍ وَآلِهِ الطَّاهِرِينَ.\nاللَّهُمَّ زَيِّنَّا بِالْعِلْمِ وَالْحِلْمِ، وَاجْعَلْ أَلْسِنَتَنَا ذَاكِرَةً لَكَ وَقُلُوبَنَا خَاشِعَةً لَكَ.\nوَارْزُقْنَا صِدْقَ الْقَوْلِ وَحُسْنَ الْعَمَلِ، إِنَّكَ أَنْتَ الْوَهَّابُ الْكَرِيمُ.", |
|||
"translation": "Revised text segment for correction 3...", |
|||
"share_link": "https://dovodi.newhorizonco.uk/arguments/hadith/hadis-ru-1-7c2df773/corrections/alternative-translation-3", |
|||
"hadis_info": { |
|||
"id": 1891, |
|||
"number": 1, |
|||
"slug": "the-merit-of-seeking-knowledge" |
|||
}, |
|||
"address": [ |
|||
"Tirmidhi, Abu Isa Muhammad ibn Isa (died 279 AH), \"Jami' al-Sahih (Sunan At-Tirmidhi)\", book: virtues, chapter: virtues of Ali ibn Abu Talib, volume 5, page 633, hadith 3713, research: Ahmad Muhammad Shakir and others, Mustafa al-Babi al-Halabi Publishing House, Egypt, 2nd edition, 1395 - 1975, in five volumes." |
|||
], |
|||
"images": [], |
|||
"references": [ |
|||
{ |
|||
"id": 4035, |
|||
"book": null, |
|||
"author": null, |
|||
"edition": null, |
|||
"volume_info": null, |
|||
"hadith_number": null, |
|||
"volume": null, |
|||
"pages": null, |
|||
"address": "Tirmidhi, Abu Isa Muhammad ibn Isa (died 279 AH), \"Jami' al-Sahih (Sunan At-Tirmidhi)\", book: virtues, chapter: virtues of Ali ibn Abu Talib, volume 5, page 633, hadith 3713, research: Ahmad Muhammad Shakir and others, Mustafa al-Babi al-Halabi Publishing House, Egypt, 2nd edition, 1395 - 1975, in five volumes.", |
|||
"url": null, |
|||
"open_book_url": null, |
|||
"citation_summary": "", |
|||
"images": [], |
|||
"images_count": 0, |
|||
"book_title": null, |
|||
"book_authors": [], |
|||
"edition_info": null |
|||
} |
|||
], |
|||
"links": [ |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка Первая ссылка ссылкассы..." |
|||
}, |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка." |
|||
}, |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка." |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"id": 24, |
|||
"title": "Context Clarification #2", |
|||
"slug": "context-clarification-2", |
|||
"narrator": "زُرارَةُ بْنُ أَعْيَنَ الشَّيبانِيّ", |
|||
"description": "بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ\r\nالْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ، وَالصَّلَاةُ وَالسَّلَامُ عَلَى سَيِّدِنَا مُحَمَّدٍ وَآلِهِ الطَّاهِرِينَ.\r\nاللَّهُمَّ زَيِّنَّا بِالْعِلْمِ وَالْحِلْمِ، وَاجْعَلْ أَلْسِنَتَنَا ذَاكِرَةً لَكَ وَقُلُوبَنَا خَاشِعَةً لَكَ.\r\nوَارْزُقْنَا صِدْقَ الْقَوْلِ وَحُسْنَ الْعَمَلِ، إِنَّكَ أَنْتَ الْوَهَّابُ الْكَرِيمُ.", |
|||
"translation": "Revised text segment for correction 2...", |
|||
"share_link": "https://dovodi.newhorizonco.uk/arguments/hadith/hadis-ru-1-7c2df773/corrections/context-clarification-2", |
|||
"hadis_info": { |
|||
"id": 1891, |
|||
"number": 1, |
|||
"slug": "the-merit-of-seeking-knowledge" |
|||
}, |
|||
"address": [ |
|||
"Tirmidhi, Abu Isa Muhammad ibn Isa (died 279 AH), \"Jami' al-Sahih (Sunan At-Tirmidhi)\", book: virtues, chapter: virtues of Ali ibn Abu Talib, volume 5, page 633, hadith 3713, research: Ahmad Muhammad Shakir and others, Mustafa al-Babi al-Halabi Publishing House, Egypt, 2nd edition, 1395 - 1975, in five volumes." |
|||
], |
|||
"images": [ |
|||
{ |
|||
"id": 85, |
|||
"image": "https://testserver/media/hadis/correction_images/image.png", |
|||
"thumbnail": "https://testserver/media/hadis/correction_images/image.png" |
|||
} |
|||
], |
|||
"references": [ |
|||
{ |
|||
"id": 4036, |
|||
"book": null, |
|||
"author": null, |
|||
"edition": null, |
|||
"volume_info": null, |
|||
"hadith_number": null, |
|||
"volume": null, |
|||
"pages": null, |
|||
"address": "Tirmidhi, Abu Isa Muhammad ibn Isa (died 279 AH), \"Jami' al-Sahih (Sunan At-Tirmidhi)\", book: virtues, chapter: virtues of Ali ibn Abu Talib, volume 5, page 633, hadith 3713, research: Ahmad Muhammad Shakir and others, Mustafa al-Babi al-Halabi Publishing House, Egypt, 2nd edition, 1395 - 1975, in five volumes.", |
|||
"url": null, |
|||
"open_book_url": null, |
|||
"citation_summary": "", |
|||
"images": [ |
|||
{ |
|||
"id": 85, |
|||
"image": "https://testserver/media/hadis/correction_images/image.png", |
|||
"thumbnail": "https://testserver/media/hadis/correction_images/image.png", |
|||
"priority": 0 |
|||
} |
|||
], |
|||
"images_count": 1, |
|||
"book_title": null, |
|||
"book_authors": [], |
|||
"edition_info": null |
|||
} |
|||
], |
|||
"links": {} |
|||
} |
|||
], |
|||
"interpretations": [ |
|||
{ |
|||
"id": 12, |
|||
"title": null, |
|||
"slug": "cat-l3-25-7f5bcb", |
|||
"narrator": "زُرارَةُ بْنُ أَعْيَنَ الشَّيبانِيّ", |
|||
"text": "<p dir=\"rtl\"><span style=\"color: #e65050;\">الْمَسْأَلَةُ الثَّامِنَةُ : قَوْلُهُ : { أَهْلَ الْبَيْتِ }</span></p>\n\n<p dir=\"rtl\">رُوِيَ عَنْ عُمَرَ بْنِ أَبِي سَلَمَةَ أَنَّهُ قَالَ : { لَمَّا نَزَلَتْ هَذِهِ الْآيَةُ عَلَى النَّبِيِّ صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ : { إنَّمَا يُرِيدُ اللَّهُ لِيُذْهِبَ عَنْكُمْ الرِّجْسَ أَهْلَ الْبَيْتِ وَيُطَهِّرَكُمْ تَطْهِيرًا } فِي بَيْتِ أُمِّ سَلَمَةَ دَعَا النَّبِيُّ صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ <span style=\"color: #e65050;\">فَاطِمَةَ وَحَسَنًا وَحُسَيْنًا</span> ، وَجَعَلَ <span style=\"color: #e65050;\">عَلِيًّا</span> خَلْفَ ظَهْرِهِ ، وَجَلَّلَهُمْ بِكِسَاءٍ ، ثُمَّ قَالَ : اللَّهُمَّ إنَّ هَؤُلَاءِ أَهْلَ بَيْتِي ، فَأَذْهِبْ عَنْهُمْ الرِّجْسَ وَطَهِّرْهُمْ تَطْهِيرًا . قَالَتْ أُمُّ سَلَمَةَ : وَأَنَا مَعَهُمْ يَا نَبِيَّ اللَّهِ . قَالَ : أَنْتِ عَلَى مَكَانِك وَأَنْتِ عَلَى خَيْرٍ } .</p>\n\n<p dir=\"rtl\">وَرَوَى أَنَسُ بْنُ مَالِكٍ { أَنَّ رَسُولَ اللَّهِ صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ كَانَ يَمُرُّ بِبَابِ فَاطِمَةَ سِتَّةَ أَشْهُرٍ إذَا خَرَجَ إلَى صَلَاةِ الْفَجْرِ يَقُولُ : الصَّلَاةَ يَا أَهْلَ الْبَيْتِ ، إنَّمَا يُرِيدُ اللَّهُ لِيُذْهِبَ عَنْكُمْ الرِّجْسَ أَهْلَ الْبَيْتِ وَيُطَهِّرَكُمْ تَطْهِيرًا } . خَرَّجَ هَذَيْنِ الْحَدِيثَيْنِ التِّرْمِذِيُّ وَغَيْرُهُ .</p>", |
|||
"translation": "<p><span style=\"color: #e65050;\">Вопрос восьмой: (что означают) слова: Ахл аль-бейт</span></p>\n\n<p>Передают от Умар ибн Аби Саламе, что когда был ниспослан аят «Аллах хочет удалить скверну от вас, о Люди дома (Ахл аль-бейт), и очистить вас наилучшим очищением» (Сура 33, аят 33) в доме Ум Саламы, Посланник Аллаха (с) позвал к себе <span style=\"color: #e65050;\">Фатиму, Хасана и Хусейна</span>, затем накрыл их своей накидкой, а <span style=\"color: #e65050;\">Али</span> был за Пророком, Пророк и его накрыл. После того, как Пророк накрыл их всех накидкой, он изволил сказать следующее: «О, Аллах, они люди моего дома, очисти же их наилучшим очищением!». Ум Салама говорит: «Я сказала: «О, Пророк Аллаха! Я тоже с ними?» Посланник Аллаха изволил сказать: «Ты оставайся при своем положении, и ты в добре».</p>\n\n<p>Передают от Анас Ибн Малика: Поистине посланник Аллах (мир ему и благословение Аллаха!) шесть месяцев проходил мимо <span style=\"color: #e65050;\">двери Фатимы</span>, когда выходил на утреннюю молитву, и говорил: время молитвы, о Ахл аль бейт! \"Аллах хочет удалить скверну от вас, о Люди дома (Ахл аль-бейт), и очистить вас наилучшим очищением\" (Сура 33, аят 33).</p>\n\n<p>Эти два хадиса привели Тирмизи и другие.</p>", |
|||
"category_info": { |
|||
"id": 1036, |
|||
"slug": "reflections", |
|||
"title": "Reflections" |
|||
}, |
|||
"address": [ |
|||
"Tirmidhi, Abu Isa Muhammad ibn Isa (died 279 AH), \"Jami' al-Sahih (Sunan At-Tirmidhi)\", book: virtues, chapter: virtues of Ali ibn Abu Talib, volume 5, page 633, hadith 3713, research: Ahmad Muhammad Shakir and others, Mustafa al-Babi al-Halabi Publishing House, Egypt, 2nd edition, 1395 - 1975, in five volumes." |
|||
], |
|||
"images": [], |
|||
"links": [ |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка Первая ссылка ссылкассы..." |
|||
}, |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка." |
|||
}, |
|||
{ |
|||
"link": "google.com", |
|||
"title": "Первая ссылка." |
|||
} |
|||
], |
|||
"references": [ |
|||
{ |
|||
"id": 76, |
|||
"book_title": "last book", |
|||
"book_authors": [ |
|||
{ |
|||
"id": 9, |
|||
"name": "sheykh hamid" |
|||
} |
|||
], |
|||
"edition_info": null, |
|||
"volume_info": null, |
|||
"hadith_number": null, |
|||
"volume": "", |
|||
"pages": "", |
|||
"address": "Tirmidhi, Abu Isa Muhammad ibn Isa (died 279 AH), \"Jami' al-Sahih (Sunan At-Tirmidhi)\", book: virtues, chapter: virtues of Ali ibn Abu Talib, volume 5, page 633, hadith 3713, research: Ahmad Muhammad Shakir and others, Mustafa al-Babi al-Halabi Publishing House, Egypt, 2nd edition, 1395 - 1975, in five volumes.", |
|||
"url": null, |
|||
"images": [] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,415 @@ |
|||
import os |
|||
import gzip |
|||
import json |
|||
import sqlite3 |
|||
import hashlib |
|||
from pathlib import Path |
|||
from django.core.management.base import BaseCommand |
|||
from django.conf import settings |
|||
from django.db import transaction |
|||
from apps.hadis.models import ( |
|||
Hadis, |
|||
HadisCategory, |
|||
HadisInterpretation, |
|||
HadisCorrection, |
|||
HadisDatabaseVersion |
|||
) |
|||
|
|||
|
|||
class Command(BaseCommand): |
|||
help = "Export Hadis and Categories into an optimized, compressed SQLite database for offline mobile sync." |
|||
|
|||
def add_arguments(self, parser): |
|||
parser.add_argument( |
|||
'--notes', |
|||
type=str, |
|||
default='', |
|||
help='Release notes for this SQLite database version' |
|||
) |
|||
parser.add_argument( |
|||
'--force-version', |
|||
type=int, |
|||
default=None, |
|||
help='Force a specific version number' |
|||
) |
|||
|
|||
def handle(self, *args, **options): |
|||
self.stdout.write(self.style.SUCCESS("Starting Hadis SQLite database generation (Single-File Architecture)...")) |
|||
|
|||
# 1. Determine destination and version number |
|||
latest_ver = HadisDatabaseVersion.objects.order_by('-version').first() |
|||
if options['force_version'] is not None: |
|||
new_version = options['force_version'] |
|||
else: |
|||
new_version = (latest_ver.version + 1) if latest_ver else 1 |
|||
|
|||
output_dir = Path(settings.MEDIA_ROOT) / 'hadis_db' |
|||
output_dir.mkdir(parents=True, exist_ok=True) |
|||
|
|||
temp_db_path = output_dir / "temp_hadis_build.sqlite" |
|||
final_gz_name = "hadis_offline.sqlite.gz" |
|||
final_gz_path = output_dir / final_gz_name |
|||
|
|||
if temp_db_path.exists(): |
|||
temp_db_path.unlink() |
|||
|
|||
# 2. Initialize SQLite database |
|||
conn = sqlite3.connect(str(temp_db_path)) |
|||
cursor = conn.cursor() |
|||
|
|||
# Optimize SQLite for bulk writes |
|||
cursor.execute("PRAGMA synchronous = OFF;") |
|||
cursor.execute("PRAGMA journal_mode = MEMORY;") |
|||
cursor.execute("PRAGMA encoding = 'UTF-8';") |
|||
|
|||
self.stdout.write("Creating SQLite tables and indexes...") |
|||
self._create_tables(cursor) |
|||
|
|||
# 3. Export data |
|||
categories_count = self._export_categories(cursor) |
|||
interp_count = self._export_category_interpretations(cursor) |
|||
hadis_count, corr_count = self._export_hadiths_and_corrections(cursor) |
|||
|
|||
conn.commit() |
|||
|
|||
# Create indexes after insertion for maximum performance |
|||
self.stdout.write("Building indexes...") |
|||
self._create_indexes(cursor) |
|||
conn.commit() |
|||
conn.close() |
|||
|
|||
# 4. Gzip compress directly to the single target file |
|||
self.stdout.write(f"Compressing database to single file: {final_gz_name}...") |
|||
hasher = hashlib.md5() |
|||
temp_gz_path = output_dir / "temp_hadis_build.sqlite.gz" |
|||
|
|||
with open(temp_db_path, 'rb') as f_in: |
|||
with gzip.open(temp_gz_path, 'wb', compresslevel=9) as f_out: |
|||
while chunk := f_in.read(1024 * 1024): |
|||
f_out.write(chunk) |
|||
hasher.update(chunk) |
|||
|
|||
checksum = hasher.hexdigest() |
|||
temp_size = temp_db_path.stat().st_size |
|||
|
|||
# Atomic replacement: replace final_gz_path with temp_gz_path |
|||
if final_gz_path.exists(): |
|||
final_gz_path.unlink() |
|||
temp_gz_path.rename(final_gz_path) |
|||
file_size = final_gz_path.stat().st_size |
|||
|
|||
# Clean up any remaining temp files in output_dir |
|||
temp_db_path.unlink(missing_ok=True) |
|||
for extra_file in output_dir.iterdir(): |
|||
if extra_file.name != final_gz_name: |
|||
try: |
|||
extra_file.unlink(missing_ok=True) |
|||
except OSError: |
|||
pass |
|||
|
|||
# 5. Record version in database (Single Active Record) |
|||
with transaction.atomic(): |
|||
# Delete old records to keep DB clean |
|||
HadisDatabaseVersion.objects.all().delete() |
|||
db_version = HadisDatabaseVersion.objects.create( |
|||
version=new_version, |
|||
file=f"hadis_db/{final_gz_name}", |
|||
file_size=file_size, |
|||
checksum_md5=checksum, |
|||
hadis_count=hadis_count, |
|||
categories_count=categories_count, |
|||
is_active=True, |
|||
notes=options['notes'], |
|||
) |
|||
|
|||
self.stdout.write(self.style.SUCCESS( |
|||
f"Successfully updated single Hadis SQLite DB to v{new_version}!\n" |
|||
f" - Uncompressed size: {temp_size / (1024*1024):.2f} MB\n" |
|||
f" - Gzipped size: {file_size / (1024*1024):.2f} MB\n" |
|||
f" - Hadiths: {hadis_count}\n" |
|||
f" - Categories: {categories_count}\n" |
|||
f" - Interpretations: {interp_count}\n" |
|||
f" - Corrections: {corr_count}\n" |
|||
f" - MD5 Checksum: {checksum}\n" |
|||
f" - File path: {final_gz_path}" |
|||
)) |
|||
|
|||
def _create_tables(self, cursor): |
|||
cursor.executescript(""" |
|||
CREATE TABLE IF NOT EXISTS categories ( |
|||
id INTEGER PRIMARY KEY, |
|||
title TEXT, |
|||
slug TEXT UNIQUE, |
|||
source_type TEXT, |
|||
sect_type TEXT |
|||
); |
|||
|
|||
CREATE TABLE IF NOT EXISTS category_interpretations ( |
|||
id INTEGER PRIMARY KEY, |
|||
category_id INTEGER, |
|||
title TEXT, |
|||
slug TEXT, |
|||
narrator TEXT, |
|||
text TEXT, |
|||
translation TEXT, |
|||
references_json TEXT, |
|||
links_json TEXT, |
|||
FOREIGN KEY (category_id) REFERENCES categories (id) |
|||
); |
|||
|
|||
CREATE TABLE IF NOT EXISTS hadiths ( |
|||
id INTEGER PRIMARY KEY, |
|||
slug TEXT UNIQUE, |
|||
category_id INTEGER, |
|||
category_slug TEXT, |
|||
title TEXT, |
|||
title_narrator TEXT, |
|||
text TEXT, |
|||
translation_json TEXT, |
|||
address TEXT, |
|||
share_link TEXT, |
|||
hadis_status_id INTEGER, |
|||
status_title TEXT, |
|||
status_color TEXT, |
|||
status_main_color_code TEXT, |
|||
status_text TEXT, |
|||
tags_json TEXT, |
|||
references_json TEXT, |
|||
reference_images_json TEXT, |
|||
narrators_json TEXT, |
|||
explanations_json TEXT, |
|||
FOREIGN KEY (category_id) REFERENCES categories (id) |
|||
); |
|||
|
|||
CREATE TABLE IF NOT EXISTS hadith_corrections ( |
|||
id INTEGER PRIMARY KEY, |
|||
hadis_id INTEGER, |
|||
title TEXT, |
|||
slug TEXT, |
|||
narrator TEXT, |
|||
description TEXT, |
|||
translation TEXT, |
|||
share_link TEXT, |
|||
address TEXT, |
|||
images_json TEXT, |
|||
references_json TEXT, |
|||
links_json TEXT, |
|||
FOREIGN KEY (hadis_id) REFERENCES hadiths (id) |
|||
); |
|||
""") |
|||
|
|||
def _create_indexes(self, cursor): |
|||
cursor.executescript(""" |
|||
CREATE INDEX IF NOT EXISTS idx_cat_slug ON categories(slug); |
|||
CREATE INDEX IF NOT EXISTS idx_interp_cat ON category_interpretations(category_id); |
|||
CREATE INDEX IF NOT EXISTS idx_hadith_cat ON hadiths(category_id); |
|||
CREATE INDEX IF NOT EXISTS idx_hadith_slug ON hadiths(slug); |
|||
CREATE INDEX IF NOT EXISTS idx_corr_hadis ON hadith_corrections(hadis_id); |
|||
""") |
|||
|
|||
def _export_categories(self, cursor): |
|||
cats = HadisCategory.objects.all() |
|||
rows = [ |
|||
( |
|||
c.id, |
|||
json.dumps(c.title, ensure_ascii=False) if isinstance(c.title, (dict, list)) else (c.title or ''), |
|||
c.slug, |
|||
getattr(c, 'source_type', None), |
|||
getattr(c, 'sect_type', None), |
|||
) |
|||
for c in cats |
|||
] |
|||
cursor.executemany( |
|||
"INSERT INTO categories (id, title, slug, source_type, sect_type) VALUES (?, ?, ?, ?, ?)", |
|||
rows |
|||
) |
|||
return len(rows) |
|||
|
|||
def _export_category_interpretations(self, cursor): |
|||
interps = HadisInterpretation.objects.select_related('category').prefetch_related( |
|||
'references__book_reference', 'references__images' |
|||
).all() |
|||
|
|||
rows = [] |
|||
for inp in interps: |
|||
refs_list = [] |
|||
for ref in inp.references.all(): |
|||
book = ref.book_reference |
|||
refs_list.append({ |
|||
'id': ref.id, |
|||
'book_title': getattr(book, 'title', None), |
|||
'address': getattr(ref, 'address', None), |
|||
'edition': getattr(ref, 'edition_id', None), |
|||
'volume': getattr(ref, 'volume_id', None), |
|||
'pages': getattr(ref, 'pages', None), |
|||
'hadith_number': getattr(ref, 'hadith_number', None), |
|||
}) |
|||
|
|||
rows.append(( |
|||
inp.id, |
|||
inp.category_id, |
|||
json.dumps(inp.title, ensure_ascii=False) if isinstance(inp.title, (dict, list)) else (inp.title or ''), |
|||
inp.slug, |
|||
inp.narrator or '', |
|||
inp.text or '', |
|||
json.dumps(inp.translation, ensure_ascii=False) if isinstance(inp.translation, (dict, list)) else (inp.translation or ''), |
|||
json.dumps(refs_list, ensure_ascii=False), |
|||
json.dumps(inp.links or [], ensure_ascii=False), |
|||
)) |
|||
|
|||
cursor.executemany( |
|||
"""INSERT INTO category_interpretations |
|||
(id, category_id, title, slug, narrator, text, translation, references_json, links_json) |
|||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""", |
|||
rows |
|||
) |
|||
return len(rows) |
|||
|
|||
def _export_hadiths_and_corrections(self, cursor): |
|||
hadiths = ( |
|||
Hadis.objects |
|||
.filter(status=True) |
|||
.select_related('category', 'hadis_status') |
|||
.prefetch_related( |
|||
'tags', |
|||
'references__book_reference__author', |
|||
'references__images', |
|||
'transmitters__transmitter__reliability', |
|||
'transmitters__uncertain_transmitters__reliability', |
|||
'transmitters__narrator_layer', |
|||
'hadiscorrection_set__references__images', |
|||
) |
|||
.order_by('id') |
|||
) |
|||
|
|||
hadis_rows = [] |
|||
correction_rows = [] |
|||
|
|||
for h in hadiths: |
|||
# 1. Status Block |
|||
status_id = h.hadis_status.id if h.hadis_status else None |
|||
status_title = h.hadis_status.title if h.hadis_status else None |
|||
status_color = h.hadis_status.color if h.hadis_status else None |
|||
status_code = h.hadis_status.main_color_code if h.hadis_status else None |
|||
|
|||
# 2. Tags |
|||
tags_list = [{'id': t.id, 'title': t.title} for t in h.tags.all()] |
|||
|
|||
# 3. References & Reference Images |
|||
refs_list = [] |
|||
ref_imgs_list = [] |
|||
for ref in h.references.all(): |
|||
book = ref.book_reference |
|||
authors = [{'id': book.author.id, 'name': book.author.name}] if book and book.author else [] |
|||
refs_list.append({ |
|||
'id': ref.id, |
|||
'title': book.title if book else None, |
|||
'authors': authors, |
|||
'share_link': getattr(book, 'share_link', None) if book else None, |
|||
}) |
|||
for img in ref.images.all(): |
|||
ref_imgs_list.append({ |
|||
'id': img.id, |
|||
'thumbnail': img.thumbnail.url if img.thumbnail else None, |
|||
'priority': img.priority, |
|||
}) |
|||
|
|||
# 4. Narrators |
|||
transmitters_data = [] |
|||
for tr in h.transmitters.all(): |
|||
t = tr.transmitter |
|||
rel = t.reliability if t else None |
|||
transmitters_data.append({ |
|||
'id': t.id if t else None, |
|||
'name': t.full_name if t else None, |
|||
'slug': t.slug if t else None, |
|||
'layer_id': tr.narrator_layer_id, |
|||
'is_uncertain': tr.is_uncertain, |
|||
'reliability': { |
|||
'id': rel.id, |
|||
'title': rel.title, |
|||
'slug': rel.slug, |
|||
'color': rel.color, |
|||
'main_color_code': rel.main_color_code, |
|||
} if rel else None, |
|||
}) |
|||
|
|||
# 5. Explanations |
|||
explanations_data = [] |
|||
if hasattr(h, 'explanations') and h.explanations: |
|||
for exp in h.explanations.all(): |
|||
explanations_data.append({ |
|||
'title': exp.title, |
|||
'detail': getattr(exp, 'detail', '') |
|||
}) |
|||
|
|||
hadis_rows.append(( |
|||
h.id, |
|||
h.slug, |
|||
h.category_id, |
|||
h.category.slug if h.category else None, |
|||
json.dumps(h.title, ensure_ascii=False) if isinstance(h.title, (dict, list)) else (h.title or ''), |
|||
json.dumps(h.title_narrator, ensure_ascii=False) if isinstance(h.title_narrator, (dict, list)) else (h.title_narrator or ''), |
|||
h.text or '', |
|||
json.dumps(h.translation or [], ensure_ascii=False), |
|||
json.dumps(h.address, ensure_ascii=False) if isinstance(h.address, (dict, list)) else (h.address or ''), |
|||
h.share_link or '', |
|||
status_id, |
|||
json.dumps(status_title, ensure_ascii=False) if isinstance(status_title, (dict, list)) else (status_title or ''), |
|||
status_color or '', |
|||
status_code or '', |
|||
json.dumps(h.hadis_status_text, ensure_ascii=False) if isinstance(h.hadis_status_text, (dict, list)) else (h.hadis_status_text or ''), |
|||
json.dumps(tags_list, ensure_ascii=False), |
|||
json.dumps(refs_list, ensure_ascii=False), |
|||
json.dumps(ref_imgs_list, ensure_ascii=False), |
|||
json.dumps({'transmitters': transmitters_data}, ensure_ascii=False), |
|||
json.dumps(explanations_data, ensure_ascii=False), |
|||
)) |
|||
|
|||
# 6. Corrections |
|||
for corr in h.hadiscorrection_set.all(): |
|||
corr_imgs = [] |
|||
corr_refs = [] |
|||
for cref in corr.references.all(): |
|||
for cimg in cref.images.all(): |
|||
if cimg.image: |
|||
corr_imgs.append({'id': cimg.id, 'image': cimg.image.url}) |
|||
corr_refs.append({ |
|||
'id': cref.id, |
|||
'address': getattr(cref, 'address', None), |
|||
}) |
|||
|
|||
correction_rows.append(( |
|||
corr.id, |
|||
h.id, |
|||
json.dumps(corr.title, ensure_ascii=False) if isinstance(corr.title, (dict, list)) else (corr.title or ''), |
|||
corr.slug, |
|||
corr.narrator or '', |
|||
corr.text or '', |
|||
json.dumps(corr.translation, ensure_ascii=False) if isinstance(corr.translation, (dict, list)) else (corr.translation or ''), |
|||
corr.share_link or '', |
|||
corr.address if hasattr(corr, 'address') else '', |
|||
json.dumps(corr_imgs, ensure_ascii=False), |
|||
json.dumps(corr_refs, ensure_ascii=False), |
|||
json.dumps(corr.links or [], ensure_ascii=False), |
|||
)) |
|||
|
|||
cursor.executemany( |
|||
"""INSERT INTO hadiths ( |
|||
id, slug, category_id, category_slug, title, title_narrator, text, |
|||
translation_json, address, share_link, hadis_status_id, status_title, |
|||
status_color, status_main_color_code, status_text, tags_json, |
|||
references_json, reference_images_json, narrators_json, explanations_json |
|||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", |
|||
hadis_rows |
|||
) |
|||
|
|||
cursor.executemany( |
|||
"""INSERT INTO hadith_corrections ( |
|||
id, hadis_id, title, slug, narrator, description, translation, |
|||
share_link, address, images_json, references_json, links_json |
|||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", |
|||
correction_rows |
|||
) |
|||
|
|||
return len(hadis_rows), len(correction_rows) |
|||
@ -0,0 +1,34 @@ |
|||
# Generated by Django on 2026-09-10 |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('hadis', '0039_bookvolume_file'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.CreateModel( |
|||
name='HadisDatabaseVersion', |
|||
fields=[ |
|||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|||
('version', models.PositiveIntegerField(unique=True, verbose_name='نسخه دیتابیس')), |
|||
('file', models.FileField(upload_to='hadis_db/', verbose_name='فایل فشرده دیتابیس (.sqlite.gz)')), |
|||
('file_size', models.BigIntegerField(default=0, verbose_name='حجم فایل (بایت)')), |
|||
('checksum_md5', models.CharField(blank=True, max_length=64, verbose_name='هش MD5')), |
|||
('hadis_count', models.PositiveIntegerField(default=0, verbose_name='تعداد احادیث')), |
|||
('categories_count', models.PositiveIntegerField(default=0, verbose_name='تعداد دستهبندیها')), |
|||
('is_active', models.BooleanField(default=True, verbose_name='نسخه فعال')), |
|||
('notes', models.TextField(blank=True, verbose_name='یادداشتهای نسخه')), |
|||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='آخرین بهروزرسانی')), |
|||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='زمان ایجاد')), |
|||
], |
|||
options={ |
|||
'verbose_name': 'نسخه دیتابیس SQLite احادیث', |
|||
'verbose_name_plural': 'نسخههای دیتابیس SQLite احادیث', |
|||
'ordering': ['-version'], |
|||
}, |
|||
), |
|||
] |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue