|
|
|
@ -20,7 +20,7 @@ from ..models import ( |
|
|
|
|
|
|
|
BookReference, BookReferenceImage, BookReferenceDocument, BookAuthor, BookPublisher, BookAuthorRutba, BookAttribute, BookSubjectArea, BookType, BookTag, BookEdition, BookVolume, BookResearcher, BookEditor, |
|
|
|
|
|
|
|
Transmitters, TransmitterReliability, NarratorLayer, OpinionStatus, ScholarlyOpinion, TransmitterOpinion, TransmitterOriginalText, |
|
|
|
Transmitters, TransmitterReliability, TransmitterRelative, NarratorLayer, OpinionStatus, ScholarlyOpinion, TransmitterOpinion, TransmitterOriginalText, |
|
|
|
|
|
|
|
City, Country, Kunya, TransmitterFeature, TransmitterProfession, SahabiStatus, Madhhab, RelationType, YearValue, NarratorDate, |
|
|
|
|
|
|
|
@ -4521,6 +4521,10 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): |
|
|
|
|
|
|
|
sons = serializers.SerializerMethodField(read_only=True) |
|
|
|
|
|
|
|
relatives = serializers.SerializerMethodField(read_only=True) |
|
|
|
|
|
|
|
relatives_data = serializers.JSONField(write_only=True, required=False) |
|
|
|
|
|
|
|
sons_ids = serializers.ListField( |
|
|
|
|
|
|
|
child=serializers.IntegerField(), |
|
|
|
@ -4649,6 +4653,10 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): |
|
|
|
|
|
|
|
"sons_ids", |
|
|
|
|
|
|
|
"relatives", |
|
|
|
|
|
|
|
"relatives_data", |
|
|
|
|
|
|
|
"share_link", |
|
|
|
|
|
|
|
"created_at", |
|
|
|
@ -4661,7 +4669,7 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): |
|
|
|
|
|
|
|
"id", "slug", "share_link", "created_at", "updated_at", |
|
|
|
|
|
|
|
"reliability_detail", "father_detail", "sons", |
|
|
|
"reliability_detail", "father_detail", "sons", "relatives", |
|
|
|
|
|
|
|
"birth_year_preview", "death_year_preview", "age_at_death_preview", |
|
|
|
|
|
|
|
@ -4751,6 +4759,106 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): |
|
|
|
|
|
|
|
return result |
|
|
|
|
|
|
|
def get_relatives(self, obj): |
|
|
|
result = [] |
|
|
|
rel_types_cache = {} |
|
|
|
for rel in obj.relatives.select_related("relation_type_ref", "narrator").all(): |
|
|
|
rel_ref = rel.relation_type_ref |
|
|
|
if not rel_ref and rel.relation_type: |
|
|
|
if rel.relation_type not in rel_types_cache: |
|
|
|
rel_types_cache[rel.relation_type] = RelationType.objects.filter( |
|
|
|
Q(code=rel.relation_type) | Q(slug=rel.relation_type) |
|
|
|
).first() |
|
|
|
rel_ref = rel_types_cache[rel.relation_type] |
|
|
|
|
|
|
|
narrator_detail = None |
|
|
|
if rel.narrator: |
|
|
|
n_name = rel.narrator.get_name("en") if hasattr(rel.narrator, "get_name") else None |
|
|
|
if not n_name and isinstance(rel.narrator.full_name, list) and rel.narrator.full_name: |
|
|
|
first = rel.narrator.full_name[0] |
|
|
|
if isinstance(first, dict): |
|
|
|
n_name = first.get("text", "—") |
|
|
|
narrator_detail = { |
|
|
|
"id": rel.narrator.id, |
|
|
|
"full_name": rel.narrator.full_name, |
|
|
|
"name": n_name or rel.name or "—", |
|
|
|
"slug": rel.narrator.slug, |
|
|
|
"legacy_id": rel.narrator.legacy_id, |
|
|
|
} |
|
|
|
|
|
|
|
result.append({ |
|
|
|
"id": rel.id, |
|
|
|
"relation_type_ref": rel_ref.id if rel_ref else None, |
|
|
|
"relation_type": (rel_ref.code or rel_ref.slug) if rel_ref else rel.relation_type, |
|
|
|
"relation_value": rel_ref.title if (rel_ref and rel_ref.title) else rel.relation_value, |
|
|
|
"relation_type_detail": { |
|
|
|
"id": rel_ref.id, |
|
|
|
"code": rel_ref.code, |
|
|
|
"slug": rel_ref.slug, |
|
|
|
"title": rel_ref.title, |
|
|
|
} if rel_ref else None, |
|
|
|
"narrator": rel.narrator_id, |
|
|
|
"narrator_detail": narrator_detail, |
|
|
|
"name": rel.name, |
|
|
|
}) |
|
|
|
return result |
|
|
|
|
|
|
|
def _sync_relatives(self, instance, relatives_data): |
|
|
|
if not isinstance(relatives_data, list): |
|
|
|
return |
|
|
|
from ..models.transmitter import RELATION_TYPE_MAP |
|
|
|
instance.relatives.all().delete() |
|
|
|
for item in relatives_data: |
|
|
|
if not isinstance(item, dict): |
|
|
|
continue |
|
|
|
rel_ref_id = item.get("relation_type_ref") or item.get("relation_type_id") |
|
|
|
rel_type_str = str(item.get("relation_type") or "").strip() |
|
|
|
narrator_id = item.get("narrator") or item.get("narrator_id") |
|
|
|
custom_name = str(item.get("name") or "").strip() |
|
|
|
|
|
|
|
rel_type_obj = None |
|
|
|
if rel_ref_id not in (None, "", "null", "undefined"): |
|
|
|
try: |
|
|
|
rel_type_obj = RelationType.objects.filter(id=int(rel_ref_id)).first() |
|
|
|
except (ValueError, TypeError): |
|
|
|
pass |
|
|
|
if not rel_type_obj and rel_type_str: |
|
|
|
rel_type_obj = RelationType.objects.filter( |
|
|
|
Q(code=rel_type_str) | Q(slug=rel_type_str) |
|
|
|
).first() |
|
|
|
|
|
|
|
narrator_obj = None |
|
|
|
if narrator_id not in (None, "", "null", "undefined"): |
|
|
|
try: |
|
|
|
narrator_obj = Transmitters.objects.filter(id=int(narrator_id)).first() |
|
|
|
except (ValueError, TypeError): |
|
|
|
pass |
|
|
|
|
|
|
|
if not rel_type_obj and not rel_type_str: |
|
|
|
continue |
|
|
|
if not narrator_obj and not custom_name: |
|
|
|
continue |
|
|
|
|
|
|
|
final_rel_type = ( |
|
|
|
(rel_type_obj.code or rel_type_obj.slug or str(rel_type_obj.id)) |
|
|
|
if rel_type_obj |
|
|
|
else rel_type_str |
|
|
|
)[:50] |
|
|
|
final_rel_val = ( |
|
|
|
rel_type_obj.title |
|
|
|
if (rel_type_obj and rel_type_obj.title) |
|
|
|
else (item.get("relation_value") or RELATION_TYPE_MAP.get(final_rel_type, [])) |
|
|
|
) |
|
|
|
|
|
|
|
TransmitterRelative.objects.create( |
|
|
|
related_to=instance, |
|
|
|
relation_type_ref=rel_type_obj, |
|
|
|
relation_type=final_rel_type, |
|
|
|
relation_value=final_rel_val, |
|
|
|
narrator=narrator_obj, |
|
|
|
name=custom_name[:255], |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def to_internal_value(self, data): |
|
|
|
@ -4835,6 +4943,17 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if "relatives" in data and "relatives_data" not in data: |
|
|
|
data["relatives_data"] = data["relatives"] |
|
|
|
|
|
|
|
if "relatives_data" in data: |
|
|
|
val = data["relatives_data"] |
|
|
|
if isinstance(val, str): |
|
|
|
try: |
|
|
|
data["relatives_data"] = json.loads(val) |
|
|
|
except ValueError: |
|
|
|
pass |
|
|
|
|
|
|
|
if "sons_ids" in data: |
|
|
|
|
|
|
|
val = data["sons_ids"] |
|
|
|
@ -4967,6 +5086,8 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): |
|
|
|
|
|
|
|
sons_ids = validated_data.pop("sons_ids", None) |
|
|
|
|
|
|
|
relatives_data = validated_data.pop("relatives_data", None) |
|
|
|
|
|
|
|
kunyas_objs = validated_data.pop("kunyas", None) |
|
|
|
|
|
|
|
features_objs = validated_data.pop("features_list", None) |
|
|
|
@ -4981,6 +5102,10 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): |
|
|
|
|
|
|
|
Transmitters.objects.filter(id__in=sons_ids).update(father=instance) |
|
|
|
|
|
|
|
if relatives_data is not None: |
|
|
|
|
|
|
|
self._sync_relatives(instance, relatives_data) |
|
|
|
|
|
|
|
if kunyas_objs is not None: |
|
|
|
|
|
|
|
instance.kunyas.set(kunyas_objs) |
|
|
|
@ -5075,6 +5200,8 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): |
|
|
|
|
|
|
|
sons_ids = validated_data.pop("sons_ids", None) |
|
|
|
|
|
|
|
relatives_data = validated_data.pop("relatives_data", None) |
|
|
|
|
|
|
|
kunyas_objs = validated_data.pop("kunyas", None) |
|
|
|
|
|
|
|
features_objs = validated_data.pop("features_list", None) |
|
|
|
@ -5097,6 +5224,10 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): |
|
|
|
|
|
|
|
Transmitters.objects.filter(id__in=sons_ids).update(father=instance) |
|
|
|
|
|
|
|
if relatives_data is not None: |
|
|
|
|
|
|
|
self._sync_relatives(instance, relatives_data) |
|
|
|
|
|
|
|
if kunyas_objs is not None: |
|
|
|
|
|
|
|
instance.kunyas.set(kunyas_objs) |
|
|
|
|