Spec-Zone.ru › Django 4.0

Шаблоны

В качестве веб-фреймворка, 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:

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 установленных приложений. Это общее имя сохранено для обратной совместимости.

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 %}.

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

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. Для использования специфичных для 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/4.0/topics/templates/

Spec-Zone.ru

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