Spec-Zone.ru › Django 3.2

Шаблоны

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

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

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

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

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

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

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

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

Синтаксис

О разделе

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

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

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

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

Переменные

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

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

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:

exception TemplateDoesNotExist(msg, tried=None, backend=None, chain=None)

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

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

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

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

Template.render(context=None, request=None)

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

Если 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' движок)

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

  • /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(template_name, context=None, request=None, using=None)

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

template_name
Имя шаблона для загрузки и отображения. Если это список имён шаблонов, Django использует select_template() вместо get_template() для поиска шаблона.
context
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.

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

class DjangoTemplates

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

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

Движки шаблонов принимают следующие 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 %}.

class Jinja2

Требуется, чтобы Jinja2 был установлен:

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

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

Когда APP_DIRS имеет значение True, движки шаблонов ищут шаблоны в подкаталоге 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

Движки шаблонов также принимают следующие 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. Для использования специфичных для Django API, вы должны их настроить в среде.

Например, вы можете создать 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. Язык шаблонов Django не имеет аналога тестов Jinja2.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/3.2/topics/templates/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API