在ImageField保存后制作缩略图



我想在保存Imagefield模型后制作上传图像的缩略图。在这一刻,我得到raise异常错误:无法创建缩略图-文件类型有效吗?"。你们能告诉我怎么用吗?

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)

编辑:我设法做缩略图与下面的代码模型.py,但我现在得到一个ValueError在/images/, '缩略图'属性没有与它相关联的文件。第二个问题,我的缩略图保存在主项目目录,而不是在媒体文件夹。

新models.py

from django.contrib.auth.models import User
from django.db import models
# from main.settings import MEDIA_ROOT
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="tumbs", editable=False)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-date_added"]
def save(
self, force_insert=False, force_update=False, using=None, update_fields=None
):
if not self.image:
self.thumbnail = None
else:
size = 128, 128
im = Img.open(self.image)
im.thumbnail(size)
im.save("thumb_" + self.image.name, "PNG")
super(Image, self).save(force_insert, force_update, using, update_fields)

注意它将在每次save()时创建缩略图,考虑在它之前添加另一个检查

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)

最新更新