我正在寻找一种在保存ImageField时调整大小,压缩和优化上传图像的方法。
class Image(models.Model):
name = models.CharField(max_length=254, blank=True)
caption = models.TextField(max_length=1000, blank=True)
height = models.IntegerField()
width = models.IntegerField()
image = models.ImageField(upload_to='', height_field='height', width_field='width', storage=S3MediaStorage())
我的第一个想法是覆盖模型的save()
并在那里实现这个逻辑,但如果用户没有'我不希望重新调整大小/压缩/优化。 t更新图像文件(即,如果他只更新现有对象上的name
或caption
并保存它。)
检查新图像文件何时上传到ImageField的正确方法是什么,而不是当用户仅更改模型中的其他字段时,例如。用户更新caption
但保留其他所有内容?
如何在代码中访问上传的图像文件?即什么是包含可以传递给Pillow的实际图像文件的变量?
编辑:这是the suspected duplicate唯一的。我不是在问这个领域是否已经改变,因为这会导致误报。我问用户是否上传了一个图像文件,我会立即更改(调整大小/优化/压缩),所以如果用户立即下载他上传的图像,他会发现它有一个不同的二进制文件,随机生成的文件名,因此比较文件名或二进制文件不是有效的方法来确定用户是否正在上传不同的图像。
答案 0 :(得分:1)
您的模型可以使用其他名称。
尽管如此,您可以尝试通过post_save信号(https://docs.djangoproject.com/en/1.9/ref/signals/#post-save)
来操作图像from PIL import Image
from django.db.models.signals import post_save
@receiver(post_save, sender=Image)
def crop_image(sender, instance, **kwargs):
img = instance.image
original = Image.open(img.src.path)
# ... your code here...
编辑:道歉。跳了一下枪。您的一个实际问题是如果图像相同则不操纵图像。你可以在save()
上这样做(UNTESTED):
def save(self, **kwargs):
try:
related_img = Image.objects.get(id=self.id)
if related_img.image != self.image:
crop_me(self.image)
except Image.DoesNotExist:
# object doesn't exist. Passing...
pass
return super(Image, self).save(**kwargs)
def crop_me(img):
original_img = Image.open(img.src.path)
# ... your code here...
编辑2:如果名称更改,您可以将原始文件名保存在辅助字段
中class Image(models.Model):
image = models.ImageField(upload_to='', height_field='height', width_field='width', storage=S3MediaStorage())
__original_image_filename = None
def __init__(self, *args, **kwargs):
super(Image, self).__init__(*args, **kwargs)
self.__original_image_filename = self.image.name
def save(self, force_insert=False, force_update=False, *args, **kwargs):
if self.image.name != self.__original_image_filename:
# name changed - do something here
super(Image, self).save(force_insert, force_update, *args, **kwargs)
self.__original_image_filename = self.image.name
我正在修改另一个答案,因此可能会有一两个错误。请检查the original answer。该问题还有其他方法可以帮助您。