2

У меня есть модель для фото с двумя полями изображений. Один для исходного изображения, а другой для измененной версии исходного изображения.Django каналы для изменения размера изображения

class Photo(models.Model): 
    user = models.ForeignKey(User) 
    image_original = models.ImageField(
     upload_to=get_upload_file_name, 
     width_field="image_original_width", 
     height_field="image_original_height", 
     blank=True 
    ) 
    image_original_width = models.IntegerField(default=0) 
    image_original_height = models.IntegerField(default=0) 
    image_470 = models.ImageField(
     upload_to=get_upload_file_name, 
     width_field="image_470_width", 
     height_field="image_470_height", 
     blank=True 
    ) 
    image_470_width = models.IntegerField(default=0) 
    image_470_height = models.IntegerField(default=0) 

Причина я выбрал Джанго-channles потому, что я уже использовал его для WebSocket цели, и в документации они сказали »... И, кроме того, существует множество некритических задач что приложения могут легко разгружаться до тех пор, пока не будет отправлен ответ - например, сохранение вещей в кеш или миниатюра недавно загруженных изображений »..

Как я могу использовать Джанго-каналы, чтобы изменить размер изображения, чтобы иметь ширину 470px и высоту авто с помощью sorl-миниатюру или Джанго-imagekit или каким-либо другим способом?

+1

Я не вижу, как каналы как-то изменить размер изображений. Не могли бы вы объяснить, почему вы хотите использовать django-каналы для выполнения этой задачи и что вы подразумеваете под этим? Кроме того, вы мертвы, установленный на миниатюре? Модель с отдельными полями модели для разных версий одного и того же изображения кажется более продвинутой аллеей django-imagekit. –

+0

@ LudwikTrammer django-imagekit выглядит многообещающим. Спасибо. Я определенно попробую. И причина, по которой я выбрал django-channels, состояла в том, что я уже использовал его для цели websocket, и в документах они сказали «И кроме того, существует множество некритических задач, которые приложения могут легко разгрузить, пока после ответа был отправлен - как сохранение вещей в кеш или миниатюра недавно загруженных изображений. ". – Karl

+0

Благодарим за отзыв. Я бы предложил добавить эту информацию к исходному вопросу. –

ответ

0

Если вы хотите использовать эскиз сорва, то вам не нужно ничего делать в коде модели. Просто класс, как это:

class Photo(models.Model): 
    user = models.ForeignKey(User) 
    image = models.ImageField(
     upload_to=get_upload_file_name, 
     width_field="width", 
     height_field="height", 
     blank=True 
    ) 
    width = models.IntegerField(default=0) 
    height = models.IntegerField(default=0) 

И всякий раз, когда вам нужно 470px изображение, сделать как это в шаблоне:

{% load thumbnail %} 
... 

{# Specifying width only here. #} 
{# If you want a height constraint as well use e.g. "470x1000". #} 
{% thumbnail photo.image "470" as im %} 
    <img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"> 
{% endthumbnail %} 

Вот именно - sorl-эскиз будет заботиться об остальном (масштабирование по первому запросу, обработка кеша и т. д.). Он работает по требованию, т. Е. Изменение размера будет выполняться при первом доступе (когда встречается тег шаблона) - это нормально нормально. Единственное, что вы должны иметь в виду, это то, что мини-эскиз не будет работать хорошо, если ваше хранилище будет медленным. Если вы сохраняете носитель на локальном диске - это нормально. Если ваш бэкэнд для хранения, скажем, Amazon S3 - не делайте этого.

Удобная часть этого - вам нужны другие размеры миниатюр, вы просто скажете, что они необходимы вам, прямо в коде вашего шаблона. Никаких изменений модели не требуется.

Если вы хотите, чтобы эскизы были предварительно сгенерированы с помощью миниатюры солома, вы можете явно или просто вызвать get_thumbnail или использовать, например. a Celery задача, которая будет запускать get_thumbnail (игнорируя результат) для вас, например.

@app.task 
def ensure_thumbnail(photo_pk, size="470"): 
    photo = Photo.objects.get(pk=photo_pk) 
    get_thumbnail(photo.image, size) 

И всякий раз, когда вы видите новую загрузку, звоните ensure_thumbnail.delay(photo.pk).

Обязательно ознакомьтесь с the examples для получения дополнительной информации.


Если вы считаете, этот подход не так, как вы хотите, чтобы все было, или у вас есть медленное хранение затем использовать Джанго-imagekit. Я не очень знаком с ней (не используется в производстве сам), но на основе документации, это выглядит следующим образом:

Ваша модель будет выглядеть следующим образом:

from imagekit.models import ImageSpecField 
from imagekit.processors import ResizeToFit 
... 

class Photo(models.Model): 
    user = models.ForeignKey(User) 
    image_original = models.ImageField(
     upload_to=get_upload_file_name, 
     width_field="image_original_width", 
     height_field="image_original_height", 
     blank=True 
    ) 
    image_original_width = models.IntegerField(default=0) 
    image_original_height = models.IntegerField(default=0) 
    # I haven't found a way to not specify the height. 
    image_470 = ImageSpecField(source="image_original", 
           processors=[ResizeToFit(470, 1000)], 
           format="JPEG") 

(Как sorl-миниатюра , это фактически не создаст поле базы данных. Если вы абсолютно хотите, чтобы полностью управляемый файл независимого изображения со своим собственным полем базы данных, кажется, что ваш лучший вариант - явно создавать эскизы в Photo.save с использованием библиотеки голой подушки.)

Тогда это просто и просто:

<img src="{{ photo.image_470.url }}" 
    width="{{ photo.image_470.width }}" 
    height="{{ photo.image_470.height }}" 
    alt="..." /> 

Обязательно ознакомьтесь с документацией on caching, которая объясняет, как работает кэширование (и генерировать thumnails асинхронно, должны вы хотите это так).