Шаблоны

Django - это веб-фреймворк, поэтому ему нужен удобный способ динамической генерации HTML. Самый распространенный подход основан на шаблонах. Шаблон содержит статические части желаемого вывода HTML, а также некоторый специальный синтаксис, описывающий, как будет вставлен динамический контент. Практический пример создания HTML-страниц с помощью шаблонов см. В Урок 3 .

Проект Django может быть настроен с одним или несколькими шаблонизаторами (или даже с нулем, если вы не используете шаблоны). Django поставляет встроенные бэкенды для собственной системы шаблонов, творчески названной языком шаблонов Django (DTL), и для популярной альтернативы Jinja2 . Серверные программы для других языков шаблонов могут быть доступны у третьих лиц. Вы также можете написать свой собственный бэкэнд, см. Пользовательский бэкэнд шаблона.

Django определяет стандартный API для загрузки и рендеринга шаблонов независимо от серверной части. Загрузка состоит из поиска шаблона для данного идентификатора и его предварительной обработки, обычно компилируя его в представление в памяти. Рендеринг означает интерполяцию шаблона с данными контекста и возврат результирующей строки.

Язык шаблонов Django - это собственная система шаблонов Django. До Django 1.8 это была единственная доступная встроенная опция. Это хорошая библиотека шаблонов, хотя она довольно самоуверенная и имеет несколько особенностей. Если у вас нет веских причин для выбора другой серверной части, вам следует использовать DTL, особенно если вы пишете подключаемое приложение и собираетесь распространять шаблоны. Приложения contrib Django, которые включают шаблоны, такие как django.contrib.admin , используют DTL.

По историческим причинам как общая поддержка шаблонизаторов, так и реализация языка шаблонов Django находятся в django.template пространстве имен.

Предупреждение

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

Язык шаблонов Django

Синтаксис

Об этом разделе

Это обзор синтаксиса языка шаблонов Django. Дополнительные сведения см. В справочнике по синтаксису языка .

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

Шаблон отображается с контекстом. Визуализация заменяет переменные их значениями, которые ищутся в контексте, и выполняет теги. Все остальное выводится как есть.

Синтаксис языка шаблонов Django включает четыре конструкции.

Переменные

Переменная выводит значение из контекста, которое представляет собой dict-подобный объект, отображающий ключи к значениям.

Переменные окружены {{и }}так:

My first name is {{ first_name }}. My last name is {{ last_name }}.

В контексте этот шаблон отображает:{'first_name': 'John', 'last_name': 'Doe'}

My first name is John. My last name is Doe.

Поиск по словарю, поиск по атрибутам и поиск по списку-индексу реализованы с использованием точечной нотации:

{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}

Если переменная преобразуется в вызываемый объект, система шаблонов вызовет его без аргументов и будет использовать его результат вместо вызываемого.

Теги

Теги обеспечивают произвольную логику в процессе рендеринга.

Это определение намеренно расплывчато. Например, тег может выводить контент, служить структурой управления, например, оператором «if» или циклом «for», захватывать контент из базы данных или даже обеспечивать доступ к другим тегам шаблона.

Метки окружены {%и %}как это:

{% csrf_token %}

Большинство тегов принимают аргументы:

{% cycle 'odd' 'even' %}

Для некоторых тегов требуются начальные и конечные теги:

{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}

Ссылка встроенных тегов доступна, а также инструкции по написанию пользовательских тегов .

Фильтры

Фильтры преобразуют значения переменных и аргументов тегов.

Они выглядят так:

{{ django|title }}

В контексте этот шаблон отображает:{'django': 'the web framework for perfectionists with deadlines'}

The Web Framework For Perfectionists With Deadlines

Некоторые фильтры принимают аргумент:

{{ my_date|date:"Y-m-d" }}

Ссылка встроенных фильтров доступна, а также инструкции по написанию пользовательских фильтров .

Комментарии

Комментарии выглядят так:

{# this won't be rendered #}

Тег обеспечивает многострочные комментарии.{% comment %}

Компоненты

Об этом разделе

Это обзор API языка шаблонов Django. Подробности см. В справке по API .

Двигатель

django.template.Engineинкапсулирует экземпляр системы шаблонов Django. Основная причина создания экземпляра Engineнапрямую - это использование языка шаблонов Django вне проекта Django.

django.template.backends.django.DjangoTemplates- это тонкая оболочка, адаптирующаяся django.template.Engineк API-интерфейсу шаблонов Django.

Шаблон

django.template.Templateпредставляет собой скомпилированный шаблон. Шаблоны можно получить с помощью Engine.get_template()или Engine.from_string().

Точно так же django.template.backends.django.Templateесть тонкая оболочка, адаптирующаяся django.template.Templateк общему шаблонному API.

Контекст

django.template.Contextсодержит некоторые метаданные в дополнение к данным контекста. Он передается Template.render()для рендеринга шаблона.

django.template.RequestContextявляется подклассом, Contextкоторый хранит текущие HttpRequestи запускает процессоры контекста шаблона.

У общего API нет эквивалентной концепции. Данные контекста передаются в обычном виде, dictа при необходимости ток HttpRequestпередается отдельно.

Погрузчики

Загрузчики шаблонов отвечают за поиск шаблонов, их загрузку и возврат Templateобъектов.

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

Контекстные процессоры

Процессоры контекста - это функции, которые получают текущее значение HttpRequestв качестве аргумента и возвращают dictданные, которые необходимо добавить в контекст визуализации.

Их основное использование - добавление общих данных, общих для всех шаблонов, в контекст без повторения кода в каждом представлении.

Django предоставляет множество встроенных контекстных процессоров , и вы также можете реализовать свои собственные дополнительные контекстные процессоры.

Поддержка шаблонизаторов

Конфигурация

Движки шаблонов настраиваются с помощью TEMPLATESпараметра. Это список конфигураций, по одной для каждого двигателя. Значение по умолчанию пусто. settings.pyГенерируется startprojectкоманда определяет более полезное значение:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            # ... some options here ...
        },
    },
]

BACKEND- это пунктирный путь Python к классу механизма шаблонов, реализующему API серверной части шаблонов Django. Встроенные бэкенды - это django.template.backends.django.DjangoTemplatesи django.template.backends.jinja2.Jinja2.

Поскольку большинство движков загружают шаблоны из файлов, конфигурация верхнего уровня для каждого движка содержит две общие настройки:

  • DIRS определяет список каталогов, в которых движок должен искать исходные файлы шаблонов в порядке поиска.
  • APP_DIRSсообщает, должен ли движок искать шаблоны внутри установленных приложений. Каждый бэкэнд определяет обычное имя для подкаталога внутри приложений, где должны храниться его шаблоны.

В редких случаях можно настроить несколько экземпляров одного и того же бэкэнда с разными параметрами. В этом случае вы должны определить уникальный NAMEдля каждого движка.

OPTIONS содержит настройки, специфичные для серверной части.

Использование

django.template.loaderМодуль определяет две функции шаблонов нагрузки.

get_template( template_name , using = None )

Эта функция загружает шаблон с заданным именем и возвращает Templateобъект.

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

get_template()пробует каждый механизм шаблонов по порядку, пока один из них не добьется успеха. Если шаблон найти не удается, он поднимается TemplateDoesNotExist. Если шаблон найден, но содержит недопустимый синтаксис, он поднимается TemplateSyntaxError.

То, как ищутся и загружаются шаблоны, зависит от серверной части и конфигурации каждого движка.

Если вы хотите ограничить поиск конкретным механизмом шаблонов, передайте этот механизм NAMEв usingаргументе.

select_template( template_name_list , using = None )

select_template()точно так же get_template(), за исключением того, что он принимает список имен шаблонов. Он пробует каждое имя по порядку и возвращает первый существующий шаблон.

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

исключениеTemplateDoesNotExist ( msg , попробовал = None , backend = None , chain = None )

Это исключение возникает, когда не удается найти шаблон. Он принимает следующие необязательные аргументы для посмертного заполнения шаблона на странице отладки:

backend
Экземпляр серверной части шаблона, из которого возникло исключение.
tried
Список источников, которые были опробованы при поиске шаблона. Это форматируется как список кортежей, содержащих , где - объект, подобный источнику, а - строка с причиной, по которой шаблон не был найден.(origin, status)originstatus
chain
Список промежуточных TemplateDoesNotExist исключений, возникающих при попытке загрузить шаблон. Это используется функциями, например get_template(), которые пытаются загрузить данный шаблон из нескольких движков.
исключениеTemplateSyntaxError ( сообщение )

Это исключение возникает, когда шаблон был найден, но содержит ошибки.

Templateобъекты, возвращаемые get_template()и select_template() должны предоставлять render()метод со следующей подписью:

Template.render( контекст = Нет , запрос = Нет )

Отображает этот шаблон с заданным контекстом.

Если contextпредоставляется, это должен быть файл dict. Если он не указан, движок отобразит шаблон с пустым контекстом.

Если requestпредоставляется, это должен быть файл HttpRequest. Затем движок должен сделать его, а также токен CSRF доступным в шаблоне. Как это достигается, зависит от каждого серверного модуля.

Вот пример алгоритма поиска. В этом примере TEMPLATESнастройка:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            '/home/html/example.com',
            '/home/html/default',
        ],
    },
    {
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [
            '/home/html/jinja2',
        ],
    },
]

Если вы позвоните get_template('story_detail.html'), вот файлы, которые Django будет искать в следующем порядке:

  • /home/html/example.com/story_detail.html( 'django'двигатель)
  • /home/html/default/story_detail.html( 'django'двигатель)
  • /home/html/jinja2/story_detail.html( 'jinja2'двигатель)

Если вы позвоните , вот что будет искать Django:select_template(['story_253_detail.html', 'story_detail.html'])

  • /home/html/example.com/story_253_detail.html( 'django'двигатель)
  • /home/html/default/story_253_detail.html( 'django'двигатель)
  • /home/html/jinja2/story_253_detail.html( 'jinja2'двигатель)
  • /home/html/example.com/story_detail.html( 'django'двигатель)
  • /home/html/default/story_detail.html( 'django'двигатель)
  • /home/html/jinja2/story_detail.html( 'jinja2'двигатель)

Когда Django находит существующий шаблон, он перестает искать.

Кончик

Вы можете использовать select_template()для гибкой загрузки шаблона. Например, если вы написали новость и хотите, чтобы у некоторых историй были собственные шаблоны, используйте что-то вроде . Это позволит вам использовать настраиваемый шаблон для отдельной истории с резервным шаблоном для историй, у которых нет настраиваемых шаблонов.select_template(['story_%s_detail.html' % story.id, 'story_detail.html'])

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

Сделайте это для собственного здравомыслия. Хранение всех шаблонов в корневом уровне одного каталога становится беспорядочным.

Чтобы загрузить шаблон из подкаталога, используйте косую черту, например:

get_template('news/story_detail.html')

Используя тот же TEMPLATESвариант, что и выше, будет предпринята попытка загрузить следующие шаблоны:

  • /home/html/example.com/news/story_detail.html( 'django'двигатель)
  • /home/html/default/news/story_detail.html( 'django'двигатель)
  • /home/html/jinja2/news/story_detail.html( 'jinja2'двигатель)

Кроме того, чтобы сократить повторяющуюся природу загрузки и рендеринга шаблонов, Django предоставляет функцию быстрого доступа, которая автоматизирует процесс.

render_to_string( имя_шаблона , context = None , request = None , using = None )

render_to_string()загружает подобный шаблон get_template()и render()немедленно вызывает его метод. Требуются следующие аргументы.

template_name
Имя шаблона для загрузки и рендеринга. Если это список имен шаблонов, Django использует select_template()вместо этого get_template()для поиска шаблона.
context
A, dictкоторый будет использоваться в качестве контекста шаблона для рендеринга.
request
Необязательный параметр, HttpRequestкоторый будет доступен в процессе рендеринга шаблона.
using
Необязательный шаблонизатор NAME. Поиск шаблона будет ограничен этой системой.

Пример использования:

from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', {'foo': 'bar'})

См. Также render()ярлык, который вызывает render_to_string()и передает результат в HttpResponseподходящий для возврата из представления.

Наконец, вы можете напрямую использовать настроенные движки:

engines

Движки шаблонов доступны в django.template.engines:

from django.template import engines

django_engine = engines['django']
template = django_engine.from_string("Hello {{ name }}!")

Ключ поиска - 'django'в этом примере - это двигатель NAME.

Встроенные бэкенды

класс DjangoTemplates

Установите BACKENDдля 'django.template.backends.django.DjangoTemplates'настройки механизма шаблонов Django.

Когда APP_DIRSесть True, DjangoTemplates движки ищут шаблоны в templatesподкаталоге установленных приложений. Это общее имя было сохранено для обратной совместимости.

DjangoTemplatesдвигатели принимают следующее OPTIONS:

  • 'autoescape': логическое значение, определяющее, включено ли автоматическое экранирование HTML.

    По умолчанию это True.

    Предупреждение

    Установите его только в том Falseслучае, если вы визуализируете не-HTML шаблоны!

  • 'context_processors': список разделенных точками путей Python к вызываемым объектам, которые используются для заполнения контекста, когда шаблон отображается с запросом. Эти вызываемые объекты принимают объект запроса в качестве аргумента и возвращают dictиз элементов, которые необходимо объединить в контекст.

    По умолчанию это пустой список.

    См. RequestContextДополнительную информацию.

  • 'debug': логическое значение, которое включает / выключает режим отладки шаблона. Если это так True, на причудливой странице ошибок будет отображаться подробный отчет для любых исключений, возникающих во время отрисовки шаблона. Этот отчет содержит соответствующий фрагмент шаблона с выделенной соответствующей строкой.

    По умолчанию используется значение DEBUGпараметра.

  • 'loaders': список разделенных точками путей Python к классам загрузчика шаблонов. Каждый Loaderкласс знает, как импортировать шаблоны из определенного источника. При желании вместо строки можно использовать кортеж. Первым элементом в кортеже должно быть Loaderимя класса, а последующие элементы передаются объекту во Loaderвремя инициализации.

    Значение по умолчанию зависит от значений DIRSи APP_DIRS.

    Подробнее см. Типы загрузчиков .

  • 'string_if_invalid': вывод в виде строки, которую система шаблонов должна использовать для недопустимых (например, неправильно написанных) переменных.

    По умолчанию это пустая строка.

    Подробнее см. Как обрабатываются недопустимые переменные .

  • 'file_charset': кодировка, используемая для чтения файлов шаблонов на диске.

    По умолчанию это 'utf-8'.

  • 'libraries': Словарь меток и разделенных точками путей Python к модулям тегов шаблонов для регистрации с помощью механизма шаблонов. Это можно использовать для добавления новых библиотек или предоставления альтернативных меток для существующих. Например:

    OPTIONS={
        'libraries': {
            'myapp_tags': 'path.to.myapp.tags',
            'admin.urls': 'django.contrib.admin.templatetags.admin_urls',
        },
    }
    

    Библиотеки можно загрузить, передав тегу соответствующий ключ словаря .{% load %}

  • 'builtins': Список разделенных точками путей Python к модулям тегов шаблонов для добавления во встроенные модули . Например:

    OPTIONS={
        'builtins': ['myapp.builtins'],
    }
    

    Теги и фильтры из встроенных библиотек можно использовать без предварительного вызова тега.{% load %}

класс Jinja2

Требуется установка Jinja2 :

$ python -m pip install Jinja2
...\> py -m pip install Jinja2

Установите BACKENDдля 'django.template.backends.jinja2.Jinja2'настройки движка Jinja2 .

Когда APP_DIRSесть True, Jinja2движки ищут шаблоны в jinja2подкаталоге установленных приложений.

Самый важный элемент в OPTIONSэто 'environment'. Это пунктирный путь Python к вызываемому объекту, возвращающему среду Jinja2. По умолчанию это 'jinja2.Environment'. Django вызывает этот вызываемый объект и передает другие параметры в качестве аргументов ключевого слова. Кроме того, Django добавляет значения по умолчанию, которые отличаются от Jinja2 несколькими параметрами:

  • 'autoescape': True
  • 'loader': загрузчик настроен для DIRSи APP_DIRS
  • 'auto_reload': settings.DEBUG
  • 'undefined': DebugUndefined if settings.DEBUG else Undefined

Jinja2двигатели также допускают следующее OPTIONS:

  • 'context_processors': список разделенных точками путей Python к вызываемым объектам, которые используются для заполнения контекста, когда шаблон отображается с запросом. Эти вызываемые объекты принимают объект запроса в качестве аргумента и возвращают dictиз элементов, которые необходимо объединить в контекст.

    По умолчанию это пустой список.

    Использование контекстных процессоров с шаблонами Jinja2 не рекомендуется.

    Контекстные процессоры полезны с шаблонами Django, потому что шаблоны Django не поддерживают функции вызова с аргументами. Поскольку Jinja2 не имеет этого ограничения, рекомендуется поместить функцию, которую вы будете использовать в качестве обработчика контекста, в глобальные переменные, доступные для шаблона, jinja2.Environmentкак описано ниже. Затем вы можете вызвать эту функцию в шаблоне:

    {{ function(request) }}
    

    Некоторые контекстные процессоры шаблонов Django возвращают фиксированное значение. Для шаблонов Jinja2 этот уровень косвенного обращения не нужен, поскольку вы можете добавлять константы прямо в jinja2.Environment.

    Исходный вариант использования для добавления процессоров контекста для Jinja2 включал:

    • Выполнение дорогостоящих вычислений, зависящих от запроса.
    • Нужен результат в каждом шаблоне.
    • Использование результата несколько раз в каждом шаблоне.

    Если все эти условия не соблюдены, передача функции в шаблон больше соответствует дизайну Jinja2.

Конфигурация по умолчанию намеренно сведена к минимуму. Если шаблон отображается с запросом (например , при использовании render()), то Jinja2бэкенд добавляет глобалов request, csrf_inputи csrf_tokenв контексте. Кроме того, этот бэкэнд не создает среду, похожую на Django. Он не знает о фильтрах и тегах Django. Чтобы использовать API, специфичные для Django, вы должны настроить их в среде.

Например, вы можете создать myproject/jinja2.pyс этим контентом:

from django.templatetags.static import static
from django.urls import reverse

from jinja2 import Environment


def environment(**options):
    env = Environment(**options)
    env.globals.update({
        'static': static,
        'url': reverse,
    })
    return env

и установите для 'environment'параметра значение 'myproject.jinja2.environment'.

Тогда вы можете использовать следующие конструкции в шаблонах Jinja2:

<img src="{{ static('path/to/company-logo.png') }}" alt="Company Logo">

<a href="{{ url('admin:index') }}">Administration</a>

Концепции тегов и фильтров существуют как в языке шаблонов Django, так и в Jinja2, но они используются по-разному. Поскольку Jinja2 поддерживает передачу аргументов вызываемым объектам в шаблонах, многие функции, требующие тега шаблона или фильтра в шаблонах Django, могут быть реализованы путем вызова функции в шаблонах Jinja2, как показано в примере выше. Глобальное пространство имен Jinja2 устраняет необходимость в процессорах контекста шаблона. Язык шаблонов Django не имеет эквивалента тестов Jinja2.

Copyright ©2021 All rights reserved