3

我有一个模型,其中缩略图宽度在父对象(外键)之间变化。我需要能够将此信息提供给 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)
    #...

但如果我这样做,什么都不会发生,甚至不会生成缩略图 url。

以下将导致此异常:
AttributeError: 'ForeignKey' object has no attribute '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'
    )
    #...
4

2 回答 2

6

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

于 2013-10-09T07:58:54.013 回答
4

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

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

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

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将根据您的宽度生成一个图像文件。如果您稍后更改宽度并再次请求缩略图,我不确定存储和缓存后端的行为方式。您可能需要一个自定义文件名生成器,它可以对缩略图的宽度进行编码,以便当宽度发生变化时,将生成一个具有不同名称的新缩略图。

于 2013-01-25T03:45:31.417 回答