Процессор 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)
#...
Но если я сделаю это, ничего не произойдет, даже не будет создан URL-адрес эскиза.
И следующее это приведет к этому исключению:
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 ответа
Вы не можете ссылаться на значения экземпляра в определении модели. Вот тут-то и стало немного сложно с Джанго; Модели являются декларацией того, как будет выглядеть экземпляр при создании экземпляра, поэтому взаимозависимые поля должны ссылаться на другие поля по имени, например 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
файл изображения будет создан в соответствии с вашей шириной. Если позже вы измените ширину и снова запросите миниатюру, я не уверен, как себя поведет сервер хранения и кэширования. Вероятно, вам потребуется специальный генератор имен файлов, который может кодировать ширину миниатюры, чтобы при изменении ширины создавался новый эскиз с другим именем.
Ответ № 1 не соответствует текущей версии django-imagekit (3.0.3). И я нашел официальное решение. Пожалуйста, обратитесь http://django-imagekit.readthedocs.org/en/latest/advanced_usage.html