首页 > 解决方案 > 在 Django 中,如何使用接收器替换模型的图像?

问题描述

我正在尝试将作为模型的一部分上传的图像转换为保存时的 jpgs。我的代码创建了 jpg 并删除了原始图像(wg,tiff),但我无法用它来替换模型中的图像。换句话说,如果我创建一个项目 x 并尝试显示 x.image,则什么都没有。任何帮助将不胜感激!

模型.py:

def image_upload(instance, filename):
    ext = filename.split('.')[-1]
    filename = "{0}.{1}".format(instance.title, ext)
    return os.path.join("originals", filename)

class Item(models.Model):
    id = models.AutoField(primary_key=True)
    owner = models.ForeignKey(
        get_user_model(),
        on_delete=models.SET_NULL,
        null=True,
        blank=True
    )
    title = models.CharField(max_length=200)
    image = models.ImageField(
        upload_to=image_upload,
        blank=True,
        validators=[validate_image]
    )

@receiver(post_save, sender=Item)
def image_to_jpg(sender, instance, **kwargs):
    if kwargs.get('created') and instance.image:
        filename, file_ext = os.path.splitext(instance.image.path)
        if file_ext != ".jpg":
            im = Image.open(instance.image.path)
            im = im.convert("RGB")
            im.save(instance.image.path.replace(file_ext, ".jpg"))
            storage, path = instance.image.storage, instance.image.path
            instance.image = im
            storage.delete(path)

标签: djangoimagemodel

解决方案


我建议你看看Django ImageKit library。它会在上传时为您处理将图像处理为一种格式的逻辑。对于您的模型,您只需执行以下操作:

class Item(models.Model):
    id = models.AutoField(primary_key=True)
    owner = models.ForeignKey(get_user_model(),on_delete=models.SET_NULL, null=True, blank=True)
    title = models.CharField(max_length=200)
    image = ProcessedImageField(
        upload_to=image_upload,
        blank=True,
        validators=[validate_image], format='JPEG', options={'quality': 80}
    )

在文档中,您还可以看到它们提供的一组不同的内置处理器,例如用于调整图像大小以适应最大分辨率。

对于您的具体答案,我认为问题只是图像字段的更改没有保存在数据库中......您需要:

  • 停用post_save信号并呼叫instance.save(),然后再次激活
  • 使用模型的update()方法

但我认为 ImageKit 选项更健壮且经过良好测试。


推荐阅读