2012-03-07 111 views
1

我有一个模型包含ImageField应该在上传后调整大小。ImageField调整大小保存也更新width_field和height_field

class SomeModel(models.Model): 
    banner = ImageField(upload_to='uploaded_images', 
         width_field='banner_width', 
         height_field='banner_height') 
    banner_width = models.PositiveIntegerField(_('banner width'), editable=False) 
    banner_height = models.PositiveIntegerField(_('banner height'), editable=False) 

def save(self, *args, **kwargs): 
    super(SomeModel, self).save(*args, **kwargs) 
    resize_image(filename=self.banner.path, 
       width=MAX_BANNER_WIDTH, 
       height=MAX_BANNER_HEIGHT) 

resize_image是一个自定义函数做调整大小,和一切工作正常,除了banner_width和banner_height被填充了原始图像的尺寸,调整前。

调整大小的图像的实际尺寸可能小于给定的MAX值,所以我必须打开调整大小的文件以在调整大小后检查它的实际尺寸。然后我可以手动设置banner_widthbanner_height,并再次保存,但这不是有效的方法。 我也可以先调整大小,设置宽度和高度字段,然后保存,但在执行保存之前,位置self.banner.path处的文件不存在。

有关如何正确完成此任务的任何建议?

+0

你可以发布resize_image方法的内容吗?看起来你可以使用一些逻辑确定图像的最终大小,在保存之前设置banner_width和banner_height属性,除非在该方法中发生了某些魔术。 – 2012-03-07 22:39:33

+0

@CaseyKinsey我最近更新了这个函数来返回调整大小的图像,现在在'save'方法中,我首先调用'super(SomeModel,self).save()'然后执行'resize_image()',更新'banner_width'和' banner_height',最后再次调用'super(SomeModel,self).save()'。它的工作原理,虽然我想避免两次保存模型实例。 – Dzejkob 2012-03-08 09:11:08

回答

3

几个小时的努力有效地做到这一点之后,我改变了我的办法处理这一问题,并定义CustomImageField这样的:

class CustomImageField(ImageField): 
    attr_class = CustomImageFieldFile 

    def __init__(self, resize=False, to_width=None, to_height=None, force=True, *args, **kwargs): 
     self.resize = resize 
     if resize: 
      self.to_width = to_width 
      self.to_height = to_height 
      self.force = force 
     super(CustomImageField, self).__init__(*args, **kwargs) 


class CustomImageFieldFile(ImageFieldFile): 

    def save(self, name, content, save=True): 
     super(CustomImageFieldFile, self).save(name, content, save=save) 
     if self.field.resize: 
      resized_img = resize_image(filename=self.path, 
             width=self.field.to_width, 
             height=self.field.to_height, 
             force=self.field.force) 
      if resized_img: 
       setattr(self.instance, self.field.width_field, resized_img.size[0]) 
       setattr(self.instance, self.field.height_field, resized_img.size[1]) 

现在就可以定义:

class SomeModel(models.Model): 
    my_image = CustomImageField(resize=True, to_width=SOME_WIDTH, to_height=SOME_HEIGHT, force=False, 
           width_field='image_width', height_field='image_height') 
    image_width = models.PositiveIntegerField(editable=False) 
    image_height = models.PositiveIntegerField(editable=False) 

而且根据resize参数,图像可以在上传后自动调整大小,并且宽度/高度字段可以正确更新,而无需保存对象两次。经过快速测试,似乎工作正常。