diff --git a/apps/hadis/serializers/serializers_admin.py b/apps/hadis/serializers/serializers_admin.py index 432902c..802ef2d 100644 --- a/apps/hadis/serializers/serializers_admin.py +++ b/apps/hadis/serializers/serializers_admin.py @@ -6,7 +6,8 @@ from ..models import ( Hadis, HadisCategory, HadisStatus, HadisTag, HadisCorrection, HadisInterpretation, HadisCollection, HadisSect, HadisInCollection, HadisTransmitter, BookReference, BookReferenceImage, BookReferenceDocument, BookAuthor, BookAttribute, BookSubjectArea, BookType, BookEdition, BookVolume, Transmitters, TransmitterReliability, NarratorLayer, OpinionStatus, TransmitterOpinion, TransmitterOriginalText, - CorrectionReference, CorrectionReferenceImage, InterpretationReference, InterpretationReferenceImage + CorrectionReference, CorrectionReferenceImage, InterpretationReference, InterpretationReferenceImage, + OriginalTextReference, OriginalTextReferenceImage ) from .category import LocalizedField @@ -245,7 +246,7 @@ class AdminHadisCategoryBriefSerializer(serializers.ModelSerializer): fields = ["id", "title"] -def save_relation_reference_data(instance, validated_data, request=None, is_correction=True): +def save_relation_reference_data(instance, validated_data, request=None, is_correction=True, ref_type=None): book_reference = validated_data.pop("book_reference_id", None) address = validated_data.pop("address", None) delete_image_ids = validated_data.pop("delete_image_ids", []) @@ -255,7 +256,9 @@ def save_relation_reference_data(instance, validated_data, request=None, is_corr ref = instance.references.first() if not ref: if book_reference or address or new_images: - if is_correction: + if ref_type == "original_text": + ref = OriginalTextReference.objects.create(original_text=instance) + elif is_correction: ref = CorrectionReference.objects.create(correction=instance) else: ref = InterpretationReference.objects.create(interpretation=instance) @@ -272,7 +275,9 @@ def save_relation_reference_data(instance, validated_data, request=None, is_corr ref.images.filter(id__in=delete_image_ids).delete() for img in new_images: - if is_correction: + if ref_type == "original_text": + OriginalTextReferenceImage.objects.create(reference=ref, image=img) + elif is_correction: CorrectionReferenceImage.objects.create(reference=ref, image=img) else: InterpretationReferenceImage.objects.create(reference=ref, image=img) @@ -1026,6 +1031,25 @@ class AdminTransmitterOriginalTextSerializer(serializers.ModelSerializer): text = serializers.JSONField(required=False, default=list) translation = serializers.JSONField(required=False, default=list) + # Writable relation fields + book_reference_id = serializers.PrimaryKeyRelatedField( + queryset=BookReference.objects.all(), + required=False, + write_only=True, + allow_null=True + ) + address = serializers.CharField( + required=False, + write_only=True, + allow_null=True, + allow_blank=True + ) + delete_image_ids = serializers.ListField( + child=serializers.IntegerField(), + required=False, + write_only=True + ) + class Meta: model = TransmitterOriginalText fields = [ @@ -1038,7 +1062,85 @@ class AdminTransmitterOriginalTextSerializer(serializers.ModelSerializer): "share_link", "embedded_in", "order", + "book_reference_id", + "address", + "delete_image_ids", + ] + + def to_internal_value(self, data): + import json + data = data.copy() if hasattr(data, "copy") else dict(data) + for json_field in ["title", "text", "translation"]: + val = data.get(json_field) + if isinstance(val, str): + try: + data[json_field] = json.loads(val) + except ValueError: + pass + delete_ids = data.get("delete_image_ids") + if delete_ids: + if isinstance(delete_ids, str): + try: + data["delete_image_ids"] = json.loads(delete_ids) + except ValueError: + data["delete_image_ids"] = [int(x) for x in delete_ids.split(",") if x.strip().isdigit()] + elif isinstance(delete_ids, list): + parsed = [] + for x in delete_ids: + if isinstance(x, str) and x.strip().isdigit(): + parsed.append(int(x)) + elif isinstance(x, int): + parsed.append(x) + data["delete_image_ids"] = parsed + return super().to_internal_value(data) + + def to_representation(self, instance): + ret = super().to_representation(instance) + ref = instance.references.first() + ret["book_reference"] = ref.book_reference_id if ref else None + ret["address"] = ref.address if ref else "" + + request = self.context.get("request") + ret["images"] = [ + { + "id": img.id, + "image": request.build_absolute_uri(img.image.url) if request and img.image else img.image.url + } + for img in (ref.images.all() if ref else []) ] + return ret + + def create(self, validated_data): + request = self.context.get("request") + book_reference_id = validated_data.pop("book_reference_id", None) + address = validated_data.pop("address", None) + delete_image_ids = validated_data.pop("delete_image_ids", []) + + instance = super().create(validated_data) + + ref_data = { + "book_reference_id": book_reference_id, + "address": address, + "delete_image_ids": delete_image_ids, + } + save_relation_reference_data(instance, ref_data, request=request, ref_type="original_text") + return instance + + def update(self, instance, validated_data): + request = self.context.get("request") + book_reference_id = validated_data.pop("book_reference_id", None) + address = validated_data.pop("address", None) + delete_image_ids = validated_data.pop("delete_image_ids", []) + + instance = super().update(instance, validated_data) + + ref_data = { + "book_reference_id": book_reference_id, + "address": address, + "delete_image_ids": delete_image_ids, + } + save_relation_reference_data(instance, ref_data, request=request, ref_type="original_text") + return instance class AdminBookVolumeSerializer(serializers.ModelSerializer): diff --git a/apps/hadis/views_admin.py b/apps/hadis/views_admin.py index 55617dc..e2ff32d 100644 --- a/apps/hadis/views_admin.py +++ b/apps/hadis/views_admin.py @@ -625,10 +625,11 @@ class AdminTransmitterOriginalTextViewSet(ModelViewSet): permission_classes = [IsAuthenticated, IsSuperAdmin] authentication_classes = [TokenAuthentication] serializer_class = AdminTransmitterOriginalTextSerializer + parser_classes = (JSONParser, MultiPartParser, FormParser) pagination_class = None def get_queryset(self): - queryset = TransmitterOriginalText.objects.all() + queryset = TransmitterOriginalText.objects.all().prefetch_related("references", "references__images") transmitter_id = self.request.query_params.get("transmitter_id") if transmitter_id: queryset = queryset.filter(transmitter_id=transmitter_id)