|
|
|
@ -20,7 +20,9 @@ def safe_copy_data(data): |
|
|
|
if hasattr(data, "lists"): |
|
|
|
new_data = {} |
|
|
|
for key, values in data.lists(): |
|
|
|
if key in ["delete_image_ids", "uploaded_images"]: |
|
|
|
if key in ["subject_area", "authors", "book_references", "delete_image_ids", "uploaded_images"] or key.endswith("[]"): |
|
|
|
new_data[key] = values |
|
|
|
elif len(values) > 1: |
|
|
|
new_data[key] = values |
|
|
|
else: |
|
|
|
new_data[key] = values[0] if values else None |
|
|
|
@ -1220,6 +1222,8 @@ class AdminBookReferenceListSerializer(serializers.ModelSerializer): |
|
|
|
volume = serializers.SerializerMethodField() |
|
|
|
publisher = serializers.SerializerMethodField() |
|
|
|
year_of_publication = serializers.SerializerMethodField() |
|
|
|
thumbnail = serializers.SerializerMethodField() |
|
|
|
image = serializers.SerializerMethodField() |
|
|
|
|
|
|
|
class Meta: |
|
|
|
model = BookReference |
|
|
|
@ -1236,9 +1240,29 @@ class AdminBookReferenceListSerializer(serializers.ModelSerializer): |
|
|
|
"publisher", |
|
|
|
"year_of_publication", |
|
|
|
"rate", |
|
|
|
"thumbnail", |
|
|
|
"image", |
|
|
|
"created_at", |
|
|
|
] |
|
|
|
|
|
|
|
def get_thumbnail(self, obj): |
|
|
|
first_img = obj.images.filter(book_volume__isnull=True).order_by("order", "id").first() |
|
|
|
if first_img and first_img.image: |
|
|
|
request = self.context.get("request") |
|
|
|
if request: |
|
|
|
return absolute_https_url(first_img.image.url, request) |
|
|
|
return absolute_https_url(first_img.image.url) |
|
|
|
first_vol = obj.volumes.filter(image__isnull=False).exclude(image="").first() |
|
|
|
if first_vol and first_vol.image: |
|
|
|
request = self.context.get("request") |
|
|
|
if request: |
|
|
|
return absolute_https_url(first_vol.image.url, request) |
|
|
|
return absolute_https_url(first_vol.image.url) |
|
|
|
return None |
|
|
|
|
|
|
|
def get_image(self, obj): |
|
|
|
return self.get_thumbnail(obj) |
|
|
|
|
|
|
|
def get_volume(self, obj): |
|
|
|
vols = list(obj.volumes.all()) |
|
|
|
return vols[0].title if vols else "" |
|
|
|
@ -1289,6 +1313,29 @@ class AdminBookReferenceDetailSerializer(serializers.ModelSerializer): |
|
|
|
country_of_publication = serializers.SerializerMethodField() |
|
|
|
edition_number = serializers.SerializerMethodField() |
|
|
|
|
|
|
|
thumbnail = serializers.SerializerMethodField() |
|
|
|
image = serializers.SerializerMethodField() |
|
|
|
remove_thumbnail = serializers.BooleanField(write_only=True, required=False, default=False) |
|
|
|
remove_image = serializers.BooleanField(write_only=True, required=False, default=False) |
|
|
|
|
|
|
|
def get_thumbnail(self, obj): |
|
|
|
first_img = obj.images.filter(book_volume__isnull=True).order_by("order", "id").first() |
|
|
|
if first_img and first_img.image: |
|
|
|
request = self.context.get("request") |
|
|
|
if request: |
|
|
|
return absolute_https_url(first_img.image.url, request) |
|
|
|
return absolute_https_url(first_img.image.url) |
|
|
|
first_vol = obj.volumes.filter(image__isnull=False).exclude(image="").first() |
|
|
|
if first_vol and first_vol.image: |
|
|
|
request = self.context.get("request") |
|
|
|
if request: |
|
|
|
return absolute_https_url(first_vol.image.url, request) |
|
|
|
return absolute_https_url(first_vol.image.url) |
|
|
|
return None |
|
|
|
|
|
|
|
def get_image(self, obj): |
|
|
|
return self.get_thumbnail(obj) |
|
|
|
|
|
|
|
def get_source_url(self, obj): |
|
|
|
ed = obj.editions.first() |
|
|
|
return ed.source_url if ed else "" |
|
|
|
@ -1355,27 +1402,133 @@ class AdminBookReferenceDetailSerializer(serializers.ModelSerializer): |
|
|
|
"rate", |
|
|
|
"author", |
|
|
|
"author_detail", |
|
|
|
"thumbnail", |
|
|
|
"image", |
|
|
|
"remove_thumbnail", |
|
|
|
"remove_image", |
|
|
|
"created_at", |
|
|
|
"updated_at", |
|
|
|
"share_link", |
|
|
|
] |
|
|
|
read_only_fields = ["id", "slug", "created_at", "updated_at", "share_link"] |
|
|
|
|
|
|
|
def to_internal_value(self, data): |
|
|
|
import json |
|
|
|
mutable_data = safe_copy_data(data) |
|
|
|
for json_field in ["title", "description", "language", "publisher", "city_of_publication", "country_of_publication"]: |
|
|
|
if json_field in mutable_data: |
|
|
|
val = mutable_data.get(json_field) |
|
|
|
if isinstance(val, str): |
|
|
|
try: |
|
|
|
mutable_data[json_field] = json.loads(val) |
|
|
|
except ValueError: |
|
|
|
pass |
|
|
|
|
|
|
|
for list_field in ["subject_area", "authors"]: |
|
|
|
if list_field in mutable_data: |
|
|
|
val = mutable_data.get(list_field) |
|
|
|
if isinstance(val, str): |
|
|
|
try: |
|
|
|
parsed = json.loads(val) |
|
|
|
mutable_data[list_field] = parsed if isinstance(parsed, list) else [parsed] |
|
|
|
except ValueError: |
|
|
|
if val.isdigit(): |
|
|
|
mutable_data[list_field] = [int(val)] |
|
|
|
elif val.strip(): |
|
|
|
mutable_data[list_field] = [int(v.strip()) for v in val.split(",") if v.strip().isdigit()] |
|
|
|
else: |
|
|
|
mutable_data[list_field] = [] |
|
|
|
elif isinstance(val, int): |
|
|
|
mutable_data[list_field] = [val] |
|
|
|
elif isinstance(val, list): |
|
|
|
cleaned_list = [] |
|
|
|
for item in val: |
|
|
|
if isinstance(item, str): |
|
|
|
try: |
|
|
|
item_parsed = json.loads(item) |
|
|
|
if isinstance(item_parsed, list): |
|
|
|
cleaned_list.extend(item_parsed) |
|
|
|
else: |
|
|
|
cleaned_list.append(item_parsed) |
|
|
|
except ValueError: |
|
|
|
cleaned_list.append(int(item) if item.isdigit() else item) |
|
|
|
else: |
|
|
|
cleaned_list.append(item) |
|
|
|
mutable_data[list_field] = cleaned_list |
|
|
|
|
|
|
|
for int_field in ["number_page", "order", "type", "tag", "author"]: |
|
|
|
if int_field in mutable_data: |
|
|
|
val = mutable_data.get(int_field) |
|
|
|
if val == "" or val == "null" or val == "undefined": |
|
|
|
mutable_data[int_field] = None |
|
|
|
|
|
|
|
if "rate" in mutable_data: |
|
|
|
val = mutable_data.get("rate") |
|
|
|
if val == "" or val == "null" or val == "undefined": |
|
|
|
mutable_data["rate"] = None |
|
|
|
|
|
|
|
if "has_editions" in mutable_data: |
|
|
|
val = mutable_data.get("has_editions") |
|
|
|
if isinstance(val, str): |
|
|
|
mutable_data["has_editions"] = val.lower() in ["true", "1"] |
|
|
|
|
|
|
|
return super().to_internal_value(mutable_data) |
|
|
|
|
|
|
|
def create(self, validated_data): |
|
|
|
subject_area = validated_data.pop("subject_area", []) |
|
|
|
validated_data.pop("remove_thumbnail", False) |
|
|
|
validated_data.pop("remove_image", False) |
|
|
|
|
|
|
|
request = self.context.get("request") |
|
|
|
thumbnail = None |
|
|
|
if request and hasattr(request, "FILES"): |
|
|
|
thumbnail = request.FILES.get("thumbnail") or request.FILES.get("image") |
|
|
|
|
|
|
|
book = super().create(validated_data) |
|
|
|
if subject_area: |
|
|
|
book.subject_area.set(subject_area) |
|
|
|
|
|
|
|
if thumbnail: |
|
|
|
BookReferenceImage.objects.create( |
|
|
|
book_reference=book, |
|
|
|
book_volume=None, |
|
|
|
image=thumbnail, |
|
|
|
order=0, |
|
|
|
) |
|
|
|
return book |
|
|
|
|
|
|
|
def update(self, instance, validated_data): |
|
|
|
subject_area = validated_data.pop("subject_area", None) |
|
|
|
remove_thumbnail = validated_data.pop("remove_thumbnail", False) or validated_data.pop("remove_image", False) |
|
|
|
|
|
|
|
request = self.context.get("request") |
|
|
|
thumbnail = None |
|
|
|
if request and hasattr(request, "FILES"): |
|
|
|
thumbnail = request.FILES.get("thumbnail") or request.FILES.get("image") |
|
|
|
|
|
|
|
book = super().update(instance, validated_data) |
|
|
|
if subject_area is not None: |
|
|
|
book.subject_area.set(subject_area) |
|
|
|
|
|
|
|
if remove_thumbnail: |
|
|
|
instance.images.filter(book_volume__isnull=True, order=0).delete() |
|
|
|
|
|
|
|
if thumbnail: |
|
|
|
main_img = instance.images.filter(book_volume__isnull=True, order=0).first() |
|
|
|
if main_img: |
|
|
|
main_img.image = thumbnail |
|
|
|
main_img.save() |
|
|
|
else: |
|
|
|
BookReferenceImage.objects.create( |
|
|
|
book_reference=instance, |
|
|
|
book_volume=None, |
|
|
|
image=thumbnail, |
|
|
|
order=0, |
|
|
|
) |
|
|
|
return book |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Category Quran Verse Admin Serializers |
|
|
|
from ..models.category import CategoryQuranVerse, QuranSecondaryTranslation |
|
|
|
|
|
|
|
|