温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

使用django怎么实现在保存图像的同时压缩图像

发布时间:2021-05-07 15:38:16 来源:亿速云 阅读:182 作者:Leah 栏目:开发技术

使用django怎么实现在保存图像的同时压缩图像?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

假设我们有一个非常简单的Post模型,它将是一个图像及其描述,

from django.db import models
 
class Post(models.Model):
 text = models.TextField()
 image = models.ImageField(upload_to='images/')

但是我们要优化图像大小,这将由我们Post的image字段指出。 这样做有充分的理由-它有助于更快地加载网站/应用程序并减少我们的服务器存储。 在使用Django之前,首先让我们简单介绍一下使用Pillow进行图像压缩的概述。

使用Pillow压缩图像

Pillow是用于图像相关操作的出色Python软件包。 Image类带有用于图像io和操作的方法。 Image.open从文件路径或文件对象读取图像。 Image类的save方法将质量作为以jpg格式保存图像的可选参数,范围为1到95,此参数的默认值为75,并且设置质量大于95会导致图像尺寸大于 原本的。

from PIL import Image
im = Image.open('/some/path/to/image')
im.save('/desired/path/new_image_name.jpg', quality=70)
im.close()

使用quality参数不是减小大小的唯一方法。 例如,您可以将其与调整图像大小相结合,以获得更小的图像尺寸。

利用Django signals

信号允许某些发送者通知一组接收者已经采取了某些措施。

Django带有许多内置信号,目前,我们对django.db.models.signals.pre_save信号感兴趣,该信号将在调用模型的save()方法之前发送。 要将处理程序连接到信号,有Signal.connect方法。 要将信号附加到特定的sender(在我们的例子中是模型),我们必须给Signal.connect方法提供sender参数,例如,将pre_save信号附加到我们的Post模型(上面定义),如下所示:

pre_save.connect(our_handler, sender=Post)

Django还提供了用于连接信号的接收器装饰器,这使代码更加惯用。 因此,除了定义our_handler并进行连接之外,我们还可以将our_handler的定义修饰为

from django.dispatch import receiver
...
 
@receiver(pre_save, sender=Post)
def my_handler(sender, **kwargs):
 ...

现在,让我们完成处理程序以压缩图像。 pre_save信号还将实例参数发送到处理程序函数,该函数对应于要保存的实际实例。 当我们要检查字段是否已更新时,这特别有用,因为我们不想重复压缩图像。 因此我们可以将处理程序功能设为

from django.db.models.signals import pre_save
from django.dispatch import receiver
 
@receiver(pre_save, sender=Post)
def handle_image_compression(sender, instance, **kwargs):
 try:
  post_obj = Post.objects.get(pk=instance.pk)
 except Post.DoesNotExist:
  # the object does not exists, so compress the image
  instance.image = compress_image(instance.image)
 else:
  # the object exists, so check if the image field is updated
  if post_obj.image != instance.image:
   instance.image = compress_image(instance.image)

现在,我们的最后一项任务是编写compress_image函数,该函数将使用一个ImageField并返回一个ImageField。 PIL的Image.open()方法只能用于文件路径或文件对象。 这是一个有趣的事实,它是ImageField的超类,它镜像了python的File API,因此,我们可以像使用实际文件一样使用它。 使用Image.open的问题已解决,但是Image.save呢? 事实证明Image.save可以将图像写入BytesIO对象。 因此,我们压缩图像的功能将变为

from PIL import Image
from io import BytesIO
from django.core.files import File
def compress_image(image):
 im = Image.open(image)
 out = BytesIO()
 im.save(out, 'JPEG', quality=70)
 compressed = File(out, name=image.name)
 im.close()
 return compressed

关于使用django怎么实现在保存图像的同时压缩图像问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI