Шаблоны

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) origin status
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 ©2020 All rights reserved