【问题标题】:Compress images with Pillow in Django在 Django 中使用 Pillow 压缩图像
【发布时间】:2019-05-07 17:22:42
【问题描述】:

我有一个 Django 项目,我使用 Pillow 将图像存储在某些模型中,但我希望将这些图像压缩存储。将图像保存到模型 ImageField 时如何指示 Pillow 压缩图像?

这是一个带有 ImageField 的模型示例:

class Photo(models.Model):
    name = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Name"))
    album = models.ForeignKey(Album, on_delete=models.PROTECT, related_name='photos', verbose_name=_("Album"))
    photo = models.ImageField(verbose_name=_("Photo"))

    class Meta:
        verbose_name = _("Photo")
        verbose_name_plural =_("Photos")

    def __str__(self):
        return "[{}] {}".format(self.pk, self.name)

我可以看到文件存储后,我可以看到它与原始源文件的大小相同。

我正在使用 Django Rest Framework 从前端获取图像。

【问题讨论】:

    标签: python django django-models django-rest-framework python-imaging-library


    【解决方案1】:

    你可以覆盖模型的save方法:

    from PIL import Image
    
    class Photo(models.Model):
        name = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Name"))
        album = models.ForeignKey(Album, on_delete=models.PROTECT, related_name='photos', verbose_name=_("Album"))
        photo = models.ImageField(verbose_name=_("Photo"))
    
        def save(self, *args, **kwargs):
           instance = super(Photo, self).save(*args, **kwargs)
           image = Image.open(instance.photo.path)
           image.save(instance.photo.path,quality=20,optimize=True)
           return instance
    

    【讨论】:

    • 使用 pre_save 接收器可以达到同样的效果吗?
    • 你需要一个 post_save 信号,因为你需要之前保存的实例,才能有照片的路径。
    【解决方案2】:

    您必须使用django signals,特别是 post_save 方法。最快的实现方式就是写在models.py文件中

    from PIL import Image
    from django.db.models.signals import post_save
    
    class Photo(models.Model):
        name = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Name"))
        album = models.ForeignKey(Album, on_delete=models.PROTECT, related_name='photos', verbose_name=_("Album"))
        photo = models.ImageField(verbose_name=_("Photo"))
    
    def image_compressor(sender, **kwargs): 
        if kwargs["created"]:
            with Image.open(kwargs["instance"].photo.path) as photo:
                photo.save(kwargs["instance"].photo.path, optimize=True, quality=50)
    
    post_save.connect(image_compressor, sender=Photo)
    
           
    
    
    

    【讨论】:

      猜你喜欢
      • 2020-05-05
      • 2019-08-06
      • 2016-01-09
      • 1970-01-01
      • 2012-11-16
      • 2018-12-19
      • 2011-02-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多