Создание миниатюры после сохранения поля 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)
Вернуться на верх