from rest_framework import serializers from django.core.files.uploadedfile import SimpleUploadedFile from .models import Blog, BlogContent, BlogSeo from utils import absolute_url from utils.image_compression import maybe_compress_uploaded_file # ─── Helper: return full URL for an ImageField ──────────────────────────────── class AbsoluteImageField(serializers.ImageField): """ Wraps DRF's ImageField to return a full absolute URL on read, while accepting a real uploaded file (InMemoryUploadedFile / TemporaryUploadedFile) on write – just like a normal 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 # ─── Serializers ────────────────────────────────────────────────────────────── class AdminBlogSeoSerializer(serializers.ModelSerializer): class Meta: model = BlogSeo fields = ["id", "title", "keywords", "description", "language"] class AdminBlogContentSerializer(serializers.ModelSerializer): image = AbsoluteImageField(required=False, allow_null=True) class Meta: model = BlogContent fields = [ "id", "blog", "title", "content", "slug", "image", "order", "created_at", "updated_at", ] class AdminBlogListSerializer(serializers.ModelSerializer): """ Lightweight serializer for the admin data table. Exposes raw JSON fields so the React frontend can manage translations. """ thumbnail = AbsoluteImageField(required=False, allow_null=True) class Meta: model = Blog fields = [ "id", "title", "slogan", "summary", "slug", "thumbnail", "views_count", "created_at", "updated_at", ] read_only_fields = ["id", "views_count", "created_at", "updated_at"] class AdminBlogDetailSerializer(serializers.ModelSerializer): """ Full serializer for the admin detail/edit view. Includes nested contents and SEO data. """ thumbnail = AbsoluteImageField(required=False, allow_null=True) contents = AdminBlogContentSerializer(many=True, read_only=True) seos = AdminBlogSeoSerializer(many=True, read_only=True) class Meta: model = Blog fields = [ "id", "title", "slogan", "summary", "slug", "thumbnail", "views_count", "created_at", "updated_at", "contents", "seos", ] read_only_fields = ["id", "views_count", "created_at", "updated_at"]