将通过PIL创建的图像保存到Django模型中

15

我已经成功地使用以下代码将通过电子邮件上传到我的服务器目录中的图像创建并旋转了它:

      image = ContentFile(b64decode(part.get_payload()))
      im = Image.open(image)
      tempfile = im.rotate(90)
      tempfile.save("/srv/www/mysite.com/public_html/media/images/rotate.jpg", "JPEG")
      img = Photo(user=user)
      img.img.save('rotate.jpg', tempfile)
      img.save()

旋转后的图像存在于目录中,但当我尝试将该图像添加到我的模型时,它没有被保存。 我错过了什么? 任何帮助都将不胜感激。


是否出现了特定的错误?你可以分享一下"Photo"模型的定义吗? - Matt Hampel
我非常确定问题不在模型上。如果我将“img.img.save('rotate.jpg',tempfile)”中的“tempfile”替换为“image”,那么它就能正确保存。因此,似乎在保存图像后,我没有正确访问新创建和旋转的图像文件。 - django-d
如果保存“im”而不是“tempfile”,是否存在相同的问题? - Matt Hampel
是的,尝试了几个方法仍然无法让它工作。就像图像不是一个有效的文件对象一样。 - django-d
很抱歉,我没有太多好的想法。你现在可以绕个弯路。当使用路径时,请关闭临时文件并将其保存。如果您正在寻求效率,这不是一个很好的选择,但应该可以作为一种权宜之计。您是否查看过tempfile中的issubclass和类似功能? - Matt Hampel
2个回答

19

我用下面的代码解决了这个问题:

       image = ContentFile(b64decode(part.get_payload()))
       im = Image.open(image)
       tempfile = im.rotate(270)
       tempfile_io =StringIO.StringIO()
       tempfile.save(tempfile_io, format='JPEG')
       image_file = InMemoryUploadedFile(tempfile_io, None, 'rotate.jpg','image/jpeg',tempfile_io.len, None)
       img = Photo(user=user)
       img.img.save('rotate.jpg', image_file)
       img.save()

我在这里找到答案如何将PIL `Image`转换为Django`File`?。运行得非常顺利!!!


3
你能加上你的导入语句吗?这样我们就能知道你从哪里获取了所有所需的类。提前感谢! - Charles Haro
2
注意:从Python3变更日志中得知:StringIO和cStringIO模块已经被取消。相反地,导入io模块并使用io.StringIO或io.BytesIO分别处理文本和数据。 - Jeffrey Klardie

0
from django.db import models
from .abstract_classes import DateTimeCreatedModified
from PIL import Image
from io import BytesIO
from django.core.files.base import ContentFile
from enum import Enum

class MediaSize(Enum):
    #             size       base file name
    DEFAULT = ((1080, 1080), 'bus_default')
    MEDIUM = ((612, 612), 'bus_medium')
    THUMBNAIL = ((161, 161), 'bus_thumbnail')


class Media(DateTimeCreatedModified):

    # The original image.
    original = models.ImageField()
    # Resized images...
    default = models.ImageField()
    medium = models.ImageField()
    thumbnail = models.ImageField()




    def resizeImg(self, img_size):
        img: Image.Image = Image.open(self.original)
        img.thumbnail(img_size, Image.ANTIALIAS)

        outputIO = BytesIO()
        img.save(outputIO, format=img.format, quality=100)

        return outputIO, img


    def handleResize(self, mediaSize: MediaSize):

        imgSize = mediaSize.value[0]
        imgName = mediaSize.value[1]

        outputIO, img = self.resizeImg(imgSize)

        return {
            # Files aren't be overwritten
            # because `AWS_S3_FILE_OVERWRITE = False`
            # is set in `settings.py`.
            'name': f'{imgName}.{img.format}',
            'content': ContentFile(outputIO.getvalue()),
            'save': False,
        }



    def save(self, **kwargs):

        if not self.default:
            self.default.save(
                **self.handleResize(MediaSize.DEFAULT)
            )

        if not self.medium:
            self.medium.save(
                **self.handleResize(MediaSize.MEDIUM)
            )

        if not self.thumbnail:
            self.thumbnail.save(
                **self.handleResize(MediaSize.THUMBNAIL)
            )

        super().save(**kwargs)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接