from rest_framework import serializers from django.core.files.uploadedfile import SimpleUploadedFile from utils.image_compression import maybe_compress_uploaded_file from .models import Book, BookCollection, Category class AbsoluteImageField(serializers.ImageField): def to_internal_value(self, data): uploaded = super().to_internal_value(data) compressed_bytes = maybe_compress_uploaded_file(uploaded) if compressed_bytes is None: return uploaded return SimpleUploadedFile( name=getattr(uploaded, "name", "image"), content=compressed_bytes, content_type=getattr(uploaded, "content_type", None), ) def to_representation(self, value): if not value: return None request = self.context.get("request") url = value.url if hasattr(value, "url") else str(value) if request: return request.build_absolute_uri(url) return url class AbsoluteFileField(serializers.FileField): def to_representation(self, value): if not value: return None request = self.context.get("request") url = value.url if hasattr(value, "url") else str(value) if request: return request.build_absolute_uri(url) return url class AdminLibraryCategorySerializer(serializers.ModelSerializer): class Meta: model = Category fields = ["id", "title", "slug", "status", "created_at", "updated_at"] class AdminLibraryCollectionSerializer(serializers.ModelSerializer): class Meta: model = BookCollection fields = ["id", "title", "slug", "summary", "display_position", "status", "order", "pin_top"] class AdminBookListSerializer(serializers.ModelSerializer): thumbnail = AbsoluteImageField(required=False, allow_null=True) book_file = AbsoluteFileField(required=False, allow_null=True) categories_detail = AdminLibraryCategorySerializer(source="categories", many=True, read_only=True) class Meta: model = Book fields = [ "id", "title", "slug", "slogan", "thumbnail", "author", "publisher", "file_type", "status", "pin", "view_count", "download_count", "created_at", "updated_at", "categories_detail", "book_file", ] read_only_fields = ["id", "view_count", "download_count", "created_at", "updated_at"] from dj_language.models import Language class AdminBookDetailSerializer(serializers.ModelSerializer): thumbnail = AbsoluteImageField(required=False, allow_null=True) book_file = AbsoluteFileField(required=False, allow_null=True) categories = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(), many=True, required=False) collections = serializers.PrimaryKeyRelatedField(queryset=BookCollection.objects.all(), many=True, required=False) categories_detail = AdminLibraryCategorySerializer(source="categories", many=True, read_only=True) collections_detail = AdminLibraryCollectionSerializer(source="collections", many=True, read_only=True) remove_thumbnail = serializers.BooleanField(write_only=True, required=False, default=False) remove_book_file = serializers.BooleanField(write_only=True, required=False, default=False) language = serializers.SlugRelatedField( slug_field='code', queryset=Language.objects.all(), allow_null=True, required=False ) class Meta: model = Book fields = [ "id", "title", "slug", "slogan", "summary_title", "summary", "description", "thumbnail", "publisher", "year_of_publication", "author", "isbn", "numnber_of_volume", "language", "main_themes", "notable_works", "pages_count", "status", "pin", "view_count", "download_count", "file_type", "book_file", "created_at", "updated_at", "categories", "collections", "categories_detail", "collections_detail", "remove_thumbnail", "remove_book_file", ] read_only_fields = ["id", "view_count", "download_count", "created_at", "updated_at"] def create(self, validated_data): validated_data.pop("remove_thumbnail", False) validated_data.pop("remove_book_file", False) categories = validated_data.pop("categories", []) collections = validated_data.pop("collections", []) book = super().create(validated_data) if categories: book.categories.set(categories) if collections: book.collections.set(collections) return book def update(self, instance, validated_data): remove_thumbnail = validated_data.pop("remove_thumbnail", False) remove_book_file = validated_data.pop("remove_book_file", False) categories = validated_data.pop("categories", None) collections = validated_data.pop("collections", None) if remove_thumbnail and instance.thumbnail: instance.thumbnail.delete(save=False) instance.thumbnail = None if remove_book_file and instance.book_file: instance.book_file.delete(save=False) instance.book_file = None book = super().update(instance, validated_data) if categories is not None: book.categories.set(categories) if collections is not None: book.collections.set(collections) return book