Files
dj52/image/serializers.py
Beyhan Oğur ec28a2024d first commit
2026-04-26 22:22:29 +03:00

109 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import uuid
from io import BytesIO
from PIL import Image, ImageOps
from django.conf import settings
from django.core.files.base import ContentFile
from rest_framework import serializers
from .models import PostImages
class PostImagesSerializer(serializers.ModelSerializer):
class Meta:
model = PostImages
fields = '__all__'
class PostImageCreateSerializer(serializers.Serializer):
"""
Serializer for uploading and processing an image.
"""
image = serializers.ImageField(write_only=True, help_text="Yüklenecek resim dosyası.")
title = serializers.CharField(max_length=254, help_text="Resim için bir başlık.")
width = serializers.IntegerField(help_text="Resmin yeni genişliği (pixel).")
height = serializers.IntegerField(help_text="Resmin yeni yüksekliği (pixel).")
quality = serializers.IntegerField(default=85, min_value=1, max_value=100, help_text="JPG/WebP için kalite (1-100).")
format = serializers.ChoiceField(
choices=['png', 'webp', 'jpg', 'avif'],
default='avif',
help_text="Çıktı resim formatı."
)
def create(self, validated_data):
image_file = validated_data.pop('image')
title = validated_data.pop('title')
new_width = validated_data.pop('width')
new_height = validated_data.pop('height')
quality = validated_data.pop('quality')
output_format = validated_data.pop('format')
# Open the image with Pillow
img = Image.open(image_file)
# Preserve original metadata for the model
original_filename = image_file.name
original_size = image_file.size
# Process the image: Resize and crop to fill target dimensions (Center Crop).
# This ensures the image fills the dimensions without distortion or padding.
# ImageOps.fit resizes and crops the image to the requested size.
img = ImageOps.fit(img, (new_width, new_height), method=Image.Resampling.LANCZOS, centering=(0.5, 0.5))
# If output format does not support transparency (like JPG), convert to RGB.
# This also ensures compatibility for formats like JPEG that don't support P or RGBA.
if output_format != 'png' and img.mode != 'RGB':
img = img.convert('RGB')
# Save the processed image to an in-memory buffer
buffer = BytesIO()
# Pillow expects 'JPEG' format identifier, not 'jpg'
save_format = output_format.upper()
if save_format == 'JPG':
save_format = 'JPEG'
save_kwargs = {'format': save_format}
if output_format in ['jpg', 'webp']:
save_kwargs['quality'] = quality
img.save(buffer, **save_kwargs)
buffer.seek(0)
# Generate a unique filename and path
new_filename = f"processed/{uuid.uuid4()}.{output_format}"
file_path = os.path.join(settings.MEDIA_ROOT, new_filename)
# Ensure the directory exists
os.makedirs(os.path.dirname(file_path), exist_ok=True)
# Save the new file to the media directory
with open(file_path, 'wb') as f:
f.write(buffer.getvalue())
# Get the size of the new file
new_size = os.path.getsize(file_path)
# Get user from validated_data if provided (serializer.save(user=...))
user = validated_data.pop('user', None)
# Create the PostImages model instance
instance = PostImages.objects.create(
title=title,
user=user,
path=new_filename, # Store the relative path
processed_path=original_filename, # Let's use this field for original name for now
original_filename=original_filename,
format=output_format,
width=new_width, # Use the target width
height=new_height, # Use the target height
size=new_size,
quality=quality,
)
return instance
def to_representation(self, instance):
# Use the PostImagesSerializer to represent the created object
return PostImagesSerializer(instance).data