Browse Source
feat(hadis): implement relational models for relation types and professions
feat(hadis): implement relational models for relation types and professions
- Add RelationType and TransmitterProfession models with two-way sync - Add migrations 0063 and 0064 for relation types and professions seeding and data migration - Register RelationType admin serializer, viewset and URL routes - Update relational migration roadmap documentationmaster
7 changed files with 1150 additions and 14 deletions
-
29RELATIONAL_MIGRATION_ROADMAP.md
-
822apps/hadis/migrations/0063_relation_type_and_relations.py
-
109apps/hadis/migrations/0064_transmitter_profession_and_relations.py
-
89apps/hadis/models/transmitter.py
-
67apps/hadis/serializers/serializers_admin.py
-
8apps/hadis/urls.py
-
40apps/hadis/views_admin.py
@ -0,0 +1,822 @@ |
|||||
|
# Generated by Django 4.2.30 on 2026-10-20 16:15 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
RELATION_TYPE_DATA = [ |
||||
|
{ |
||||
|
"code": "stepfather", |
||||
|
"slug": "stepfather", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "زوج الأم", |
||||
|
"title": "زوج الأم" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "ناپدری", |
||||
|
"title": "ناپدری" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Stepfather", |
||||
|
"title": "Stepfather" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Отчим", |
||||
|
"title": "Отчим" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "stepmother", |
||||
|
"slug": "stepmother", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "زوجة الأب", |
||||
|
"title": "زوجة الأب" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "نامادری", |
||||
|
"title": "نامادری" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Stepmother", |
||||
|
"title": "Stepmother" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Мачеха", |
||||
|
"title": "Мачеха" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "uncles_and_aunts", |
||||
|
"slug": "uncles-and-aunts", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الأعمام والعمات والأخوال والخالات", |
||||
|
"title": "الأعمام والعمات والأخوال والخالات" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "عموها، عمهها، داییها و خالهها", |
||||
|
"title": "عموها، عمهها، داییها و خالهها" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Uncles and aunts", |
||||
|
"title": "Uncles and aunts" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Дяди и тёти", |
||||
|
"title": "Дяди и тёти" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "siblings", |
||||
|
"slug": "siblings", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الإخوة", |
||||
|
"title": "الإخوة" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "برادران و خواهران", |
||||
|
"title": "برادران و خواهران" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Siblings", |
||||
|
"title": "Siblings" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Сиблинги", |
||||
|
"title": "Сиблинги" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "parents", |
||||
|
"slug": "parents", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الوالدان", |
||||
|
"title": "الوالدان" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "والدین", |
||||
|
"title": "والدین" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Parents", |
||||
|
"title": "Parents" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Родители", |
||||
|
"title": "Родители" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "nephews_and_nieces", |
||||
|
"slug": "nephews-and-nieces", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "أبناء الإخوة", |
||||
|
"title": "أبناء الإخوة" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "فرزندان برادر و خواهر", |
||||
|
"title": "فرزندان برادر و خواهر" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Nephews and nieces", |
||||
|
"title": "Nephews and nieces" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Племянники", |
||||
|
"title": "Племянники" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "children", |
||||
|
"slug": "children", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الأولاد", |
||||
|
"title": "الأولاد" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "فرزندان", |
||||
|
"title": "فرزندان" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Children", |
||||
|
"title": "Children" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Дети", |
||||
|
"title": "Дети" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "stepchildren", |
||||
|
"slug": "stepchildren", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الربائب", |
||||
|
"title": "الربائب" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "فرزندان همسر (ربائب)", |
||||
|
"title": "فرزندان همسر (ربائب)" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Stepchildren", |
||||
|
"title": "Stepchildren" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Пасынки и падчерицы", |
||||
|
"title": "Пасынки и падчерицы" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "spouses", |
||||
|
"slug": "spouses", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الأزواج", |
||||
|
"title": "الأزواج" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "همسران", |
||||
|
"title": "همسران" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Spouses", |
||||
|
"title": "Spouses" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Супруги", |
||||
|
"title": "Супруги" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "cousins", |
||||
|
"slug": "cousins", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "أبناء العمومة والخؤولة", |
||||
|
"title": "أبناء العمومة والخؤولة" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "فرزندان عمو، عمه، دایی و خاله", |
||||
|
"title": "فرزندان عمو، عمه، دایی و خاله" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Cousins", |
||||
|
"title": "Cousins" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Двоюродные братья и сестры", |
||||
|
"title": "Двоюродные братья и сестры" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "granduncles_and_grandaunts", |
||||
|
"slug": "granduncles-and-grandaunts", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "إخوة الأجداد", |
||||
|
"title": "إخوة الأجداد" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "عموها و عمههای والدین", |
||||
|
"title": "عموها و عمههای والدین" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Granduncles and grandaunts", |
||||
|
"title": "Granduncles and grandaunts" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Великие дяди и тети", |
||||
|
"title": "Великие дяди и тети" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "grandnephews_and_grandnieces", |
||||
|
"slug": "grandnephews-and-grandnieces", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "أحفاد الإخوة", |
||||
|
"title": "أحفاد الإخوة" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "نوههای برادر و خواهر", |
||||
|
"title": "نوههای برادر و خواهر" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Grandnephews and grandnieces", |
||||
|
"title": "Grandnephews and grandnieces" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Внучатые племянники", |
||||
|
"title": "Внучатые племянники" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "grandchildren_and_great_grandchildren", |
||||
|
"slug": "grandchildren-and-great-grandchildren", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الأحفاد وأبناء الأحفاد", |
||||
|
"title": "الأحفاد وأبناء الأحفاد" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "نوهها و نبیرهها", |
||||
|
"title": "نوهها و نبیرهها" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Grandchildren and great-grandchildren", |
||||
|
"title": "Grandchildren and great-grandchildren" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Внуки и правнуки", |
||||
|
"title": "Внуки и правнуки" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "grandparents", |
||||
|
"slug": "grandparents", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الأجداد", |
||||
|
"title": "الأجداد" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "پدربزرگ و مادربزرگ", |
||||
|
"title": "پدربزرگ و مادربزرگ" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Grandparents", |
||||
|
"title": "Grandparents" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Прародители", |
||||
|
"title": "Прародители" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "foster_mother", |
||||
|
"slug": "foster-mother", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "المرضعة", |
||||
|
"title": "المرضعة" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "مادر رضاعی (دایه)", |
||||
|
"title": "مادر رضاعی (دایه)" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Foster mother", |
||||
|
"title": "Foster mother" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Молочная мать", |
||||
|
"title": "Молочная мать" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "tribe", |
||||
|
"slug": "tribe", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "القبيلة", |
||||
|
"title": "القبيلة" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "طایفه و قبیله", |
||||
|
"title": "طایفه و قبیله" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Tribe", |
||||
|
"title": "Tribe" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Племя", |
||||
|
"title": "Племя" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "foster_children", |
||||
|
"slug": "foster-children", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الرضاء", |
||||
|
"title": "الرضاء" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "فرزندان رضاعی", |
||||
|
"title": "فرزندان رضاعی" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Foster children", |
||||
|
"title": "Foster children" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Молочные дети", |
||||
|
"title": "Молочные дети" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "in_laws", |
||||
|
"slug": "in-laws", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الأصهار والأختان", |
||||
|
"title": "الأصهار والأختان" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "بستگان سببی (خانواده همسر)", |
||||
|
"title": "بستگان سببی (خانواده همسر)" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "In-laws", |
||||
|
"title": "In-laws" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Свойственники", |
||||
|
"title": "Свойственники" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "students", |
||||
|
"slug": "students", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "التلاميذ", |
||||
|
"title": "التلاميذ" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "شاگردان", |
||||
|
"title": "شاگردان" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Students", |
||||
|
"title": "Students" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Ученики", |
||||
|
"title": "Ученики" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "owners_and_masters", |
||||
|
"slug": "owners-and-masters", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الملاك", |
||||
|
"title": "الملاك" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "مالکان و اربابان", |
||||
|
"title": "مالکان و اربابان" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Owners and masters", |
||||
|
"title": "Owners and masters" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Хозяева и владельцы", |
||||
|
"title": "Хозяева и владельцы" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "other_relatives", |
||||
|
"slug": "other-relatives", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الأقارب", |
||||
|
"title": "الأقارب" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "سایر خویشاوندان", |
||||
|
"title": "سایر خویشاوندان" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Other relatives", |
||||
|
"title": "Other relatives" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Другие родственники", |
||||
|
"title": "Другие родственники" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "friends_and_companions", |
||||
|
"slug": "friends-and-companions", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الأصحاب", |
||||
|
"title": "الأصحاب" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "دوستان و همراهان", |
||||
|
"title": "دوستان و همراهان" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Friends and companions", |
||||
|
"title": "Friends and companions" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Друзья и сподвижники", |
||||
|
"title": "Друзья и сподвижники" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "allies", |
||||
|
"slug": "allies", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الحلفاء", |
||||
|
"title": "الحلفاء" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "همپیمانان (حلفاء)", |
||||
|
"title": "همپیمانان (حلفاء)" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Allies", |
||||
|
"title": "Allies" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Союзники", |
||||
|
"title": "Союзники" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "neighbors", |
||||
|
"slug": "neighbors", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "الجيران", |
||||
|
"title": "الجيران" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "همسایگان", |
||||
|
"title": "همسایگان" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Neighbors", |
||||
|
"title": "Neighbors" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Соседи", |
||||
|
"title": "Соседи" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "wards_and_proteges", |
||||
|
"slug": "wards-and-proteges", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "المحضونون", |
||||
|
"title": "المحضونون" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "تحت تکفل و پرورشیافتگان", |
||||
|
"title": "تحت تکفل و پرورشیافتگان" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Wards and proteges", |
||||
|
"title": "Wards and proteges" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Подопечные и воспитанники", |
||||
|
"title": "Подопечные и воспитанники" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "cousins_of_parents", |
||||
|
"slug": "cousins-of-parents", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "أبناء عمومة الآباء", |
||||
|
"title": "أبناء عمومة الآباء" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "فرزندان عمو، عمه، دایی و خاله والدین", |
||||
|
"title": "فرزندان عمو، عمه، دایی و خاله والدین" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Cousins of parents", |
||||
|
"title": "Cousins of parents" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Двоюродные дяди и тети", |
||||
|
"title": "Двоюродные дяди и тети" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "cousins_of_grandparents", |
||||
|
"slug": "cousins-of-grandparents", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "أبناء عمومة الأجداد", |
||||
|
"title": "أبناء عمومة الأجداد" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "فرزندان عمو، عمه، دایی و خاله اجداد", |
||||
|
"title": "فرزندان عمو، عمه، دایی و خاله اجداد" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Cousins of grandparents", |
||||
|
"title": "Cousins of grandparents" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Двоюродные дедушки и бабушки", |
||||
|
"title": "Двоюродные дедушки и бабушки" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "cousins_children", |
||||
|
"slug": "cousins-children", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "أبناء أبناء العمومة", |
||||
|
"title": "أبناء أبناء العمومة" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "فرزندان عموزادهها و داییزادهها", |
||||
|
"title": "فرزندان عموزادهها و داییزادهها" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Cousins children", |
||||
|
"title": "Cousins children" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Двоюродные племянники", |
||||
|
"title": "Двоюродные племянники" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"code": "cousins_grandchildren_and_great_grandchildren", |
||||
|
"slug": "cousins-grandchildren-and-great-grandchildren", |
||||
|
"title": [ |
||||
|
{ |
||||
|
"language_code": "ar", |
||||
|
"text": "أحفاد أبناء العمومة", |
||||
|
"title": "أحفاد أبناء العمومة" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "fa", |
||||
|
"text": "نوههای عموزادهها و داییزادهها", |
||||
|
"title": "نوههای عموزادهها و داییزادهها" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "en", |
||||
|
"text": "Cousins grandchildren and great-grandchildren", |
||||
|
"title": "Cousins grandchildren and great-grandchildren" |
||||
|
}, |
||||
|
{ |
||||
|
"language_code": "ru", |
||||
|
"text": "Двоюродные внуки и правнуки", |
||||
|
"title": "Двоюродные внуки и правнуки" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
] |
||||
|
|
||||
|
|
||||
|
def seed_and_migrate_relation_types(apps, schema_editor): |
||||
|
RelationType = apps.get_model('hadis', 'RelationType') |
||||
|
TransmitterRelative = apps.get_model('hadis', 'TransmitterRelative') |
||||
|
|
||||
|
rel_type_map = {} |
||||
|
for item in RELATION_TYPE_DATA: |
||||
|
obj, _ = RelationType.objects.get_or_create( |
||||
|
code=item["code"], |
||||
|
defaults={ |
||||
|
"slug": item["slug"], |
||||
|
"title": item["title"], |
||||
|
}, |
||||
|
) |
||||
|
rel_type_map[item["code"]] = obj |
||||
|
|
||||
|
# Link existing TransmitterRelative records |
||||
|
updated_count = 0 |
||||
|
for code, rel_obj in rel_type_map.items(): |
||||
|
count = TransmitterRelative.objects.filter(relation_type=code).update(relation_type_ref=rel_obj) |
||||
|
updated_count += count |
||||
|
print(f"Linked {updated_count} TransmitterRelative records to RelationType.") |
||||
|
|
||||
|
|
||||
|
def reverse_seed(apps, schema_editor): |
||||
|
pass |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('hadis', '0062_madhhab_and_relations'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.CreateModel( |
||||
|
name='RelationType', |
||||
|
fields=[ |
||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
|
('code', models.CharField(blank=True, max_length=100, null=True, unique=True, verbose_name='Code')), |
||||
|
('title', models.JSONField(default=list, verbose_name='Title')), |
||||
|
('slug', models.SlugField(allow_unicode=True, blank=True, max_length=255, unique=True, verbose_name='slug')), |
||||
|
('description', models.JSONField(blank=True, default=list, 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': 'Relation Type', |
||||
|
'verbose_name_plural': 'Relation Types', |
||||
|
'ordering': ['slug', 'id'], |
||||
|
}, |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='transmitterrelative', |
||||
|
name='relation_type_ref', |
||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='relative_links', to='hadis.relationtype', verbose_name='Relation Type Ref'), |
||||
|
), |
||||
|
migrations.RunPython(seed_and_migrate_relation_types, reverse_seed), |
||||
|
] |
||||
@ -0,0 +1,109 @@ |
|||||
|
# Generated by Django 4.2.30 on 2026-10-21 10:21 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
from django.utils.text import slugify |
||||
|
|
||||
|
|
||||
|
def populate_professions_from_existing_records(apps, schema_editor): |
||||
|
TransmitterProfession = apps.get_model('hadis', 'TransmitterProfession') |
||||
|
Transmitters = apps.get_model('hadis', 'Transmitters') |
||||
|
|
||||
|
profession_by_text = {} |
||||
|
for p in TransmitterProfession.objects.all(): |
||||
|
if isinstance(p.title, list): |
||||
|
for entry in p.title: |
||||
|
if isinstance(entry, dict): |
||||
|
txt = (entry.get('text') or entry.get('title') or '').strip().lower() |
||||
|
if txt: |
||||
|
profession_by_text[txt] = p |
||||
|
|
||||
|
def get_or_create_profession(json_list): |
||||
|
if not json_list or not isinstance(json_list, list): |
||||
|
return None |
||||
|
cleaned = [] |
||||
|
lookup_keys = [] |
||||
|
for entry in json_list: |
||||
|
if isinstance(entry, dict): |
||||
|
lang = (entry.get('language_code') or '').strip() |
||||
|
txt = (entry.get('text') or entry.get('title') or '').strip() |
||||
|
if lang and txt: |
||||
|
cleaned.append({'language_code': lang, 'text': txt, 'title': txt}) |
||||
|
lookup_keys.append(txt.lower()) |
||||
|
if not cleaned: |
||||
|
return None |
||||
|
|
||||
|
for key in lookup_keys: |
||||
|
if key in profession_by_text: |
||||
|
existing = profession_by_text[key] |
||||
|
existing_langs = { |
||||
|
item.get('language_code'): item |
||||
|
for item in (existing.title or []) |
||||
|
if isinstance(item, dict) and item.get('language_code') |
||||
|
} |
||||
|
updated = False |
||||
|
for item in cleaned: |
||||
|
if item['language_code'] not in existing_langs: |
||||
|
existing_langs[item['language_code']] = item |
||||
|
updated = True |
||||
|
if updated: |
||||
|
existing.title = list(existing_langs.values()) |
||||
|
existing.save(update_fields=['title']) |
||||
|
for k in lookup_keys: |
||||
|
profession_by_text[k] = existing |
||||
|
return existing |
||||
|
|
||||
|
first_text = cleaned[0]['text'] |
||||
|
slug_val = slugify(first_text, allow_unicode=True)[:240] or 'profession' |
||||
|
prof_obj = TransmitterProfession.objects.create(title=cleaned, slug=slug_val) |
||||
|
for k in lookup_keys: |
||||
|
profession_by_text[k] = prof_obj |
||||
|
return prof_obj |
||||
|
|
||||
|
for tr in Transmitters.objects.all().iterator(): |
||||
|
source_data = getattr(tr, 'occupation', None) or getattr(tr, 'profession', None) |
||||
|
if source_data and isinstance(source_data, list): |
||||
|
p_obj = get_or_create_profession(source_data) |
||||
|
if p_obj: |
||||
|
tr.professions_list.add(p_obj) |
||||
|
if not tr.profession: |
||||
|
tr.profession = p_obj.title |
||||
|
tr.save(update_fields=['profession']) |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('hadis', '0063_relation_type_and_relations'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.CreateModel( |
||||
|
name='TransmitterProfession', |
||||
|
fields=[ |
||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
|
('title', models.JSONField(default=list, verbose_name='Title')), |
||||
|
('slug', models.SlugField(allow_unicode=True, blank=True, max_length=255, null=True, verbose_name='slug')), |
||||
|
('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': 'Transmitter Profession', |
||||
|
'verbose_name_plural': 'Transmitter Professions', |
||||
|
'ordering': ('-created_at', '-id'), |
||||
|
}, |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='transmitters', |
||||
|
name='profession', |
||||
|
field=models.JSONField(blank=True, default=list, verbose_name='Profession'), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='transmitters', |
||||
|
name='professions_list', |
||||
|
field=models.ManyToManyField(blank=True, related_name='transmitters', to='hadis.transmitterprofession', verbose_name='Professions (M2M)'), |
||||
|
), |
||||
|
migrations.RunPython( |
||||
|
populate_professions_from_existing_records, |
||||
|
reverse_code=migrations.RunPython.noop, |
||||
|
), |
||||
|
] |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue