Создание миниатюры после сохранения поля ImageField
Я хочу сделать миниатюру загруженного изображения после сохранения модели Imagefield. В данный момент я получаю ошибку raise Exception error: Could not create thumbnail - is the file type valid?". Не могли бы вы мне помочь, как заставить его работать?
models.py
from django.contrib.auth.models import User
from django.db import models
from PIL import Image as Img
class Image(models.Model):
img_owner = models.ForeignKey(User, on_delete=models.CASCADE, default=User)
image = models.ImageField(null=True, blank=False)
thumbnail = models.ImageField(upload_to="thumbs", editable=False)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-date_added"]
def save(self, *args, **kwargs):
if not self.make_thumbnail():
# set to a default thumbnail
raise Exception("Could not create thumbnail - is the file type valid?")
super(Image, self).save(*args, **kwargs)
def make_thumbnail(self):
size = 128, 128
im = Img.open(self.image)
im.thumbnail(size)
im.save(self.image.name + ".thumbnail", "PNG")
seralizers.py
from rest_framework import serializers
from .models import Image
class ImageSerializer(serializers.ModelSerializer):
author = serializers.ReadOnlyField(source="img_owner.username")
thumbnail = serializers.ReadOnlyField()
class Meta:
model = Image
fields = ["url", "author", "img_owner", "image", "thumbnail", "date_added"]
views.py
from rest_framework import permissions, viewsets
from .models import Image
from .serializers import ImageSerializer
class ImageViewSet(viewsets.ModelViewSet):
queryset = Image.objects.all()
serializer_class = ImageSerializer
permission_classes = [permissions.IsAuthenticated]
"""
Bellow definition overrides queryset and filter images by loged user.
"""
def get_queryset(self):
user = self.request.user
return Image.objects.filter(img_owner=user)
Обратите внимание, что он будет создавать миниатюру при каждом сохранении(), подумайте о добавлении еще одной проверки перед этим
from django.contrib.auth.models import User
from django.db import models
from django.conf import settings # it's the correct way to import settings
from PIL import Image as Img
from pathlib import Path
class Image(models.Model):
img_owner = models.ForeignKey(User, on_delete=models.CASCADE, default=User)
image = models.ImageField(null=True, blank=False)
thumbnail = models.ImageField(upload_to="tumbs", editable=False)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-date_added"] # it's not recommended to set ordering at model level.
def save(self, *args, **kwargs):
if not self.image:
self.thumbnail = None # note, this will not delete the file
else:
size = 128, 128
im = Img.open(self.image)
im.thumbnail(size)
name = Path(self.image.name)
# omit Path() if MEDIA_ROOT is already a Path object
thb_path = Path(settings.MEDIA_ROOT) / f"thumb_{name.stem}.png"
self.thumbnail = thb_path.name # it's should be relative path
im.save(thb_path, "PNG") # if it doesn't like Path, str() it
super().save(*args, **kwargs)