Как я могу эффективно отображать изображение в Django?

Я пишу небольшое приложение django для обработки изображений. Я хотел бы сделать это как можно более СУХИМ, поэтому это моя цель:

Пользователь загружает файл и вводит некоторые поля, такие как заголовок, замещающий текст, заголовок и т. д.

В шаблоне я хотел бы сделать что-то вроде:

model.image.render_tag

который выведет что-то вроде:

<img src='path/image.jpg' title='title' alt_text='alt_text..' />

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

Можно также добавить второй шаблон и визуализировать его.

Теперь есть несколько способов добиться этого:

1)

Просто включите шаблон, который отображает переменную с пространством имен, и заставьте разработчика каждый раз «менять» имя переменной изображения, шаблон будет примерно таким:

<img src="{{ namespaced_image.raw.path }}" alt_text="{{ namespaced_image.alt_text }}"... />

В этом случае разработчик должен переименовать изображение в его версию с пространством имен, прежде чем включать путь.

Что-то типа:

{% with namespaced_image=image %}
    {% include images/template.html %}
{% end with %}

2)

Добавьте тег шаблона для рендеринга изображения на основе необработанной строки, которую пользователь может редактировать в настройках, например

settings.py

namespaced_image_tag="<img src={path} ... />"

и мой тег шаблона будет делать что-то вроде

@register
def rendered_tag(image)
    return namespaced_image_tag.format(path=image.raw.path, ...)

Таким образом, разработчик может просто добавить файл пользовательских тегов и использовать

{% load images_filters %}

{{ image|rendered_tag }}

3)

Смесь вышеперечисленного:

Там будет шаблон по умолчанию template.html, содержащий тег, и тег шаблона, который будет отображать шаблон, предоставляя ему изображение с пространством имен в качестве контекста.

@register
def rendered_tag(image, template="default_template.html")
    return render_template(template, namespaced_image=image)

Таким образом, разработчик может сделать что-то вроде

{% load images_filters %}
{{ image|rendered_tag }}
{{ image|rendered_tag:"custom_template_name" }}

Однако я не знаю, как рендеринг нескольких шаблонов на запрос повлияет на производительность.

Кроме того, мне не очень нравится вариант №1, потому что он непригоден для использования и чтения.

Вариант № 2 плохой, потому что я не могу использовать разные «шаблоны» и не могу расширять другие. Я также не очень люблю теги шаблонов, особенно потому, что пользователь вынужден импортировать файл в каждый используемый шаблон.

Вариант № 3 является лучшим с точки зрения удобства использования, но я чувствую, что это сильно повлияет на производительность. Какие-нибудь советы?


person XelharK    schedule 07.05.2014    source источник
comment
Что ж.. Я позволю кому-то другому дать вам конкретные подсказки, но один из распространенных ответов на ваши вопросы: Не беспокойтесь о производительности, пока вам это не нужно. Если вам нравится № 3, и он, кажется, не съедает все доступные ресурсы, дерзайте.   -  person Ambroise    schedule 07.05.2014


Ответы (1)


По моему мнению, и я думаю, что многие разделяют эту точку зрения со мной, модель не должна отвечать за свое представление в HTML, поэтому наличие model.image.render_tag кажется мне неправильным.

Единственными частями приложения, которые умеют представлять что-либо в HTML, должны быть представления и их шаблоны.

Вы можете иметь вспомогательную функцию, которая генерирует HTML для изображения и использовать его в своих представлениях, вы также можете иметь simple_tag, который ссылается на эту функцию, чтобы вы могли использовать ее в своих шаблонах.

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

Обновлять

Я продемонстрирую то, что имел в виду выше, на примере.

# inside html_utils.py

def image_to_html(image):
    return '<img src="%(path)s" title="%(title)s" alt="%(alt)s" />' % {
        'path': image.raw.path,
        'title': image.title,
        'alt': image.alt_text
    }

# inside html_template_utils.py

import html_utils
from django import template

register = template.Library()

@register.simple_tag
def image_tag(image):
    return html_utils.image_to_html(image)

{# inside images_template.html #}

{% load html_template_utils %}

<div class="images-container">
{% for image in images %}
    {% image_tag image %}
{% endfor %}
</div>

В приведенном выше коде используется вспомогательная функция image_to_html из шаблона с помощью созданного нами image_tag simple_tag. Другой возможный способ — вызвать image_to_html в представлении и передать результаты в шаблон:

# inside views.py

import html_utils

def view_images(request):
    # ...

    images_html = [html_utils.image_to_html(image) for image in images]

    # ...

    return render_to_response('images_template.html', {
        'images_html': images_html
    }, context_instance=RequestContext(request))

{# inside images_template.html #}

<div class="images-container">
{% for image_html in images_html %}
    {{ image_html }}
{% endfor %}
</div>
person mpcabd    schedule 07.05.2014
comment
Я не говорю о МОЕЙ производительности, но поскольку я хотел бы распространять это приложение, я хотел бы, чтобы оно не повлияло на производительность. Однако дело не в этом. Я не уверен, что понимаю, что вы имеете в виду под Вы можете иметь вспомогательную функцию, которая генерирует HTML для изображения и использовать его в своих представлениях, вы также можете иметь простой_тег, который ссылается на эту функцию, чтобы вы могли используйте его в своих шаблонах. Не могли бы вы рассказать об этом немного подробнее? - person XelharK; 07.05.2014
comment
Хорошо, похоже, это то, что я имел в виду, когда говорил о моем варианте №2. Можно ли это сделать только с помощью шаблона? Влияет ли на производительность тот факт, что я визуализирую другой шаблон (и, возможно, многие другие)? - person XelharK; 07.05.2014
comment
Да, это почти то же самое, но я использовал simple_tag вместо filter, потому что я считаю, что это намного динамичнее. И, как вы можете видеть в ответе SO, на который я ссылался, производительность действительно имеет значение, и она зависит от механизма шаблонов, но шаблон Django для приложений малого и среднего размера по-прежнему будет идеальным выбором. - person mpcabd; 08.05.2014