first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 22:22:29 +03:00
commit ec28a2024d
208 changed files with 23836 additions and 0 deletions

108
image/serializers.py Normal file
View File

@@ -0,0 +1,108 @@
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