django imagekit处理器:使用存储在数据库中的维度

时间:2013-01-20 17:10:12

标签: python django imagekit django-imagekit

我有一个模型,缩略图宽度在父对象之间变化(ForeignKey)。我需要能够将此信息提供给imagekit处理器。这就是我所拥有的:

class Wall(models.Model):
    #...
    width = models.SmallIntegerField(null=True, blank=True)
    #...


class Poster(models.Model):
    wall = models.ForeignKey(Wall, related_name='posters')
    #...
    original_image = models.ImageField(upload_to=upload_image_to)

    def __init__(self, *args, **kwargs):
        self.thumbnail = ImageSpecField([
                Adjust(contrast=1.2, sharpness=1.1),
                SmartResize(height=163, width=self.wall.width)
            ],
            image_field='original_image', format='PNG'
        )

        super(Poster, self).__init__(*args, **kwargs)
    #...

但是,如果我这样做,没有任何反应,甚至没有生成缩略图网址。

以下将导致此异常:
AttributeError:'ForeignKey'对象没有属性'width'

class Poster(models.Model):
    wall = models.ForeignKey(Wall, related_name='posters')
    #...
    original_image = models.ImageField(upload_to=upload_image_to)

    thumbnail = ImageSpecField([
            Adjust(contrast=1.2, sharpness=1.1),
            SmartResize(height=163, width=wall.width)
        ],
        image_field='original_image', format='PNG'
    )
    #...

2 个答案:

答案 0 :(得分:6)

#1答案不适合当前版本的django-imagekit(3.0.3)。 我找到了正式的解决方案。 请参考 http://django-imagekit.readthedocs.org/en/latest/advanced_usage.html#specs-that-change

答案 1 :(得分:4)

您无法在模型定义中引用实例值。这就是Django变得有点棘手的地方;模型是实例化时实例的声明,这就是为什么相互依赖的字段必须按名称引用其他字段,例如image_field='original_image'规范。

从imagekit的源代码中可以看出,processors可以采用要应用的静态处理器列表,也可以采用可调用的,这可以返回要在生成时应用的处理器列表。由于您希望生成在运行时根据宽度进行更改,因此您可以利用此优势。

使用processors字段出现的实例调用thumbnail callable,然后允许您查找宽度。

def thumbnail_processors(instance, file):
    # Dynamic width lookup.
    width = instance.wall.width
    return [
        Adjust(contrast=1.2, sharpness=1.1),
        SmartResize(width=width, height=163),
        ]


class Poster(models.Model):
    wall = models.ForeignKey(Wall, related_name='posters')
    #...
    original_image = models.ImageField(upload_to=upload_image_to)

    thumbnail = ImageSpecField(
        processors=thumbnail_processors,
        image_field='original_image', format='PNG'
    )
    #...

现在,当您访问该字段时,将调用thumbnail_processors以在运行时获取处理器列表,而不是在模型声明中。从您的外键获取width并执行适当的调整大小。

可能有些问题需要调查。当您访问thumbnail时,将根据您的宽度生成图像文件。如果您稍后更改宽度并再次请求缩略图,我不确定存储和缓存后端的行为方式。您可能需要一个自定义文件名生成器,它可以对缩略图的宽度进行编码,这样当宽度发生变化时,将生成一个具有不同名称的新缩略图。