2016-03-21 37 views
1

我正在寻找一种在保存ImageField时调整,压缩和优化上传图像的方法。Django如何在使用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()和实现这个逻辑,但我不想,如果用户不更新图像文件的大小调整/压缩/优化再次运行(即,如果他只更新现有对象上的namecaption并将其保存)。

  1. 什么是正确的方法来检查时,一个新的图像文件被上传到的ImageField,但不是当用户只在模型中,如改变另一个领域。用户更新caption,但保持原样?

  2. 如何在代码中访问上传的图像文件?即包含可传递给Pillow的实际图像文件的变量是什么?

编辑:这是从the suspected duplicate独特。我并不是问该领域是否发生了变化,因为这总是会导致误报。我询问用户是否上传了一个图像文件,我将立即更改(调整大小/优化/压缩),因此如果用户立即下载他上传的图像,他会发现它具有与随机生成的文件名不同的二进制文件,以及因此比较文件名或二进制文件不是有效的方法来确定用户是否正在上传不同的图像。

+0

可能重复[Django:保存时,如何检查字段是否已更改?](http://stackoverflow.com/questions/1355150/django-when-saving-how-can-you-check- if-a-field-has-changed) – rnevius

+0

@rnevius我已经添加了信息来区分这个问题,谢谢 – dtgq

回答

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()像这样(未经):

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。在这个问题上还有其他方法可以帮助你。

+1

你写了'if not self.id',然后在'if'块中,你正在做'id = self .id'。可能想解决这个问题。它应该是'如果self.id'。 – xyres

+0

固定。感谢您指出了这一点!这也是反模式(EAFP)http://docs.quantifiedcode.com/python-code-patterns/readability/asking_for_permission_instead_of_forgiveness_when_working_with_files.html –

+0

'if related_img.image!= self.image:'这可能工作,如果我保留副本原始文件上传到'related_img.image'中,但是如果我只保存原始文件的副本,该文件已被重命名为随机字符串,并且图像已被调整大小和压缩,它看起来不会有用。是否有可能只检查用户上传的图像文件? – dtgq

相关问题