我想在Imagefield模型保存后制作上传图像的缩略图。此时我收到了引发异常错误:无法创建缩略图-文件类型有效吗?”。你们能帮我如何让它工作吗?
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)
编辑:我设法用下面的代码在models.py做缩略图,但是我现在在 /images/得到一个ValueError,缩略图属性没有与之关联的文件。第二个问题我的缩略图保存在主项目目录而不是媒体文件夹中。
新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)
请注意,它会在每次保存()时创建缩略图,请考虑在它之前添加另一个检查
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)