You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

87 lines
3.2 KiB

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"]