Введение в Jinja2 и render_template

Шаблон — это HTML с дырками для данных. Jinja2 берёт шаблон, подставляет переданные значения и возвращает готовую страницу. View считает данные, шаблон их показывает.
Собирать HTML строками в Python — ад: кавычки, экранирование, перемешанная логика. Jinja2 разделяет «что показать» (данные из view) и «как показать» (разметка в шаблоне). Это и есть архитектурный принцип разделения ответственности.

Представь страницу профиля: имя, аватар, список постов. Если клеить её строками в Python — получится нечитаемое месиво. Шаблонизатор переворачивает подход: ты пишешь почти обычный HTML, а в нужных местах ставишь {{ переменная }}. Flask использует Jinja2 — мощный и популярный движок.

Шаблоны кладут в папку templates рядом с приложением. View вызывает render_template с именем файла и данными:

from flask import render_template

@app.route("/hello/<name>")
def hello(name):
    return render_template("hello.html", name=name, items=["a", "b"])

А сам шаблон templates/hello.html:

<h1>Привет, {{ name }}!</h1>
<ul>
{% for item in items %}
  <li>{{ item }}</li>
{% endfor %}
</ul>

Две конструкции: {{ ... }} выводит значение, {% ... %} — управляющая логика (циклы, условия). Это и есть язык Jinja.

Разделение данных и представления — это не вкусовщина, а принцип, который делает код поддерживаемым. Когда HTML собирается строками в Python, любая правка вёрстки означает копание в логике, а дизайнер вообще не может работать с таким кодом. Шаблоны переворачивают расклад: разметка живёт в .html-файлах, понятных даже верстальщику, а Python лишь поставляет данные. Это и есть архитектурный паттерн MVC в миниатюре: модель (данные), представление (шаблон), контроллер (view). Держи шаблоны «тупыми» — вся подготовка данных делается во view, а шаблон только показывает готовое. Тогда и логику, и вёрстку можно менять независимо, не ломая друг друга.

Как работает под капотом

Jinja не подставляет строки наивно — он компилирует шаблон в Python-функцию один раз, а потом быстро вызывает её с данными. Грубо говоря, {{ name }} превращается в кусок кода, который пишет значение name в буфер вывода.

  hello.html (текст)
       │ компиляция (один раз)
       ▼
  Python-функция render(context)
       │ вызов с {name:"Анна", items:[...]}
       ▼
  готовый HTML-текст
       │
       ▼
  Response браузеру

Чтобы прочувствовать суть подстановки, смоделируем мини-шаблонизатор: заменим {{ ключ }} на значения из словаря.

import re

def render(template, **context):
    def repl(m):
        key = m.group(1).strip()
        return str(context.get(key, ""))
    return re.sub(r"\{\{\s*(\w+)\s*\}\}", repl, template)

tpl = "Привет, {{ name }}! Тебе {{ age }} лет."
print(render(tpl, name="Анна", age=15))
print(render(tpl, name="Боб", age=20))

Запусти — один шаблон, разные данные, разный результат. Настоящий Jinja умеет циклы, условия, наследование и автоэкранирование, но базовая идея ровно такая.

Частые ошибки

  • Шаблон не в папке templates. Flask ищет шаблоны именно там; иначе TemplateNotFound.
  • Логику бизнеса тащить в шаблон. Шаблон — про отображение. Вычисления делай во view.
  • Путать {{ }} и {% %}. Двойные фигурные выводят значение, процентные — управляют потоком.

Best practices

  • Передавай в шаблон уже готовые данные, не сырые объекты с тяжёлой логикой.
  • Имена шаблонов осмысленные, структура папок повторяет блюпринты.
  • Держи шаблоны «тупыми»: минимум логики, максимум разметки.

Что запомнить

  • Шаблон отделяет представление (HTML) от логики (данные из view).
  • render_template ищет файлы в папке templates и подставляет данные.
  • {{ }} выводит значение, {% %} — управляющая логика.
  • Jinja компилирует шаблон в Python-функцию для скорости.

Итог: Jinja2 разделяет данные и представление. View готовит данные, render_template отдаёт их шаблону, шаблон через {{ }} и {% %} собирает HTML. Дальше — синтаксис Jinja подробно.

Проверьте себя
1. Чем {{ name }} отличается от {% if %} в Jinja2?
AНичем
B{{ }} выводит значение, {% %} — управляющая логика (циклы, условия)
C{{ }} для чисел, {% %} для строк
D{% %} быстрее
2. Где Flask по умолчанию ищет файлы шаблонов?
AВ корне проекта
BВ папке templates рядом с приложением
CВ папке static
DВ базе данных