Django Pillow,将图像另存为jpeg似乎无效

时间:2018-10-12 07:56:07

标签: django forms image upload python-imaging-library

早上好,

我正在使用Pillow来调整大小并将图像保存在称为Post的Django模型中。从图像字段检索图像,请检查图像是否为RGB,如果不是,则将图像转换为RGB。

最后,我要从原始图像创建缩略图,然后尝试将其保存在MEDIA_ROOT中。

即使图片已上传,它似乎也无法将图片转换为jpeg。

我在这里Django 2+ edit images with Pillow遵循了该教程,我正在尝试使其适合我的需求。

我在这里想念什么?

models.py

import os

from django.core.validators import RegexValidator
from django.db import models
from django.utils import timezone
from PIL import Image
from django.conf import settings
from django.db.models.signals import post_save
class Post(models.Model):

# Custom validators
title_validator_specialchar = RegexValidator(regex=r'^[\s*\d*a-zA-Z]{5,60}$', message="The title can't contain any special characters")

category = models.ForeignKey('Category',default=1, on_delete=models.SET_NULL, null=True)
type = models.CharField(max_length=20)
title = models.CharField(max_length=200, validators=[title_validator_specialchar])
content = models.TextField(max_length=2000)
image = models.ImageField(upload_to='%Y/%m/%d/', blank=True)
created_at = models.DateTimeField(editable=False)
updated_at = models.DateTimeField(default=timezone.now)

def save(self, *args, **kwargs):
    #On save, update timestamp date created
    if not self.id:
        self.created_at = timezone.now()
    self.updated_at = timezone.now()
    return super(Post, self).save(*args, **kwargs)

def __str__(self):
    return self.title


def resize_image(instance, **kwargs):

if instance.image:

    # we are opening image with Pillow
    img = Image.open(instance.image)

    # convert image to RGB
    if img.mode not in ('L', 'RGB'):
        img = img.convert('RGB')

    # img.size is tuple with values (width, height)
    if img.size[0] > 320 or img.size[1] > 640:

        # Using thumbnail to resize image but keep aspect ratio
        img.thumbnail((320, 640), Image.ANTIALIAS)

        # saving to original place
        # instance.image.name is in %Y/%m/%d/<name> format
        output = os.path.join(settings.MEDIA_ROOT, instance.image.name)
        img.save(output, "JPEG")

# Connect the signal with our model
post_save.connect(resize_image, Post)

3 个答案:

答案 0 :(得分:0)

信号处理程序接收发送方作为第一个参数,在post_save信号的情况下,它是模型类,而不是模型实例。

因此instance的自变量resize_image()应命名为sender,并且不包含所需的内容。这是实际实例的获取方式:

def resize_image(sender, **kwargs):
    instance = kwargs.get('instance')
    if instance and instance.image:
        ...

答案 1 :(得分:0)

由于找不到使它正常工作所需的东西,我决定使用django-imagekit。

我在模型上使用ProcessedImageField和ResizeToFill处理器;

models.py

image = ProcessedImageField(upload_to='%Y/%m/%d/', processors=[ResizeToFill(384, 216)], format='JPEG', options={'quality': 60}, blank=True)

答案 2 :(得分:0)

发生这种情况是因为您明确调用 img 以保存在 mediaroot 中,但 instance.image 保持静止。因此 django 也会保存该图像。所以我认为你必须改变 instance.image 属性而不是调用 img 来保存。为此,您必须使用 django InMemorUploadedFile

import io
from django.core.files.uploadedfile import InMemoryUploadedFile
import sys
if instance.image:

# we are opening image with Pillow
img = Image.open(instance.image)

# convert image to RGB
if img.mode not in ('L', 'RGB'):
    img = img.convert('RGB')

# img.size is tuple with values (width, height)
if img.size[0] > 320 or img.size[1] > 640:
    
    # Using thumbnail to resize image but keep aspect ratio
    img.thumbnail((320, 640), Image.ANTIALIAS)
    
    # saving to original place by changing instance.image. django will save it 
    #automatically in mediaroot
    img_io = io.BytesIO()
    img.save(img_io, "JPEG")
    instance.image = InMemoryUploadedFile(img_io, 'ImageField', 'image.jpeg', 
                    'image/jpeg',sys.getsizeof(img_io), None )
    


    

我们不能将 Image 对象直接传递给 inastance.image 因为它会引发错误。 所以我们必须将 img 转换为 InMemoryUploadedFile 对象。