Привет! До сих пор мы возвращали HTML прямо из функций-представлений. Это удобно для маленьких примеров, но в реальных проектах HTML лучше выносить в отдельные файлы — шаблоны. В Flask для этого используется шаблонизатор Jinja2.
В этой статье мы разберём:
- Настройку папки
templates - Рендеринг шаблонов
- Передачу данных в шаблоны
- Циклы и условия в шаблонах
- Наследование шаблонов
- Что нужно знать перед началом
- Основная часть
- Настройка папки templates
- Простой шаблон
- Передача данных в шаблон
- Условия в шаблонах
- Циклы в шаблонах
- Фильтры в шаблонах
- Наследование шаблонов
- Полный пример
- Задачи для закрепления
- Нюансы и подводные камни
- Папка templates
- Автоэкранирование
- Использование Python-кода
- Частые ошибки и как их избежать
- Ошибка 1: Неправильный путь к папке templates
- Ошибка 2: Забыл передать переменную в render_template()
- Ошибка 3: Неправильный синтаксис Jinja2
- Шпаргалка
- Заключение
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Установленный Flask
- Базовое понимание HTML
Совет: Jinja2 — это мощный шаблонизатор. Он позволяет отделить логику от представления и делает код чище.
Основная часть
Настройка папки templates
По умолчанию Flask ищет шаблоны в папке templates рядом с приложением.
myflaskapp/
app.py
templates/
index.html
about.htmlСовет: Папка
templatesдолжна быть на том же уровне, что иapp.py. Если это не так, можно указать путь вручную.
Простой шаблон
Создай файл templates/index.html:
<!DOCTYPE html>
<html>
<head>
<title>Главная</title>
</head>
<body>
<h1>Привет, {{ name }}!</h1>
<p>Добро пожаловать на мой сайт.</p>
</body>
</html>В app.py:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
name = "Анна"
return render_template('index.html', name=name)
if __name__ == '__main__':
app.run(debug=True)Совет:
render_template()— это функция, которая рендерит шаблон и возвращает HTML.
Передача данных в шаблон
Данные передаются через аргументы render_template():
@app.route('/user/<username>')
def user_profile(username):
user = {
'name': username,
'age': 25,
'city': 'Москва'
}
return render_template('user.html', user=user, title='Профиль')Шаблон templates/user.html:
<h1>{{ title }}</h1>
<p>Имя: {{ user.name }}</p>
<p>Возраст: {{ user.age }}</p>
<p>Город: {{ user.city }}</p>Условия в шаблонах
{% if user.age >= 18 %}
<p>Пользователь совершеннолетний</p>
{% else %}
<p>Пользователь несовершеннолетний</p>
{% endif %}Циклы в шаблонах
@app.route('/users')
def users_list():
users = [
{'name': 'Анна', 'age': 25},
{'name': 'Иван', 'age': 30},
{'name': 'Петр', 'age': 20}
]
return render_template('users.html', users=users)Шаблон templates/users.html:
<ul>
{% for user in users %}
<li>{{ user.name }} ({{ user.age }} лет)</li>
{% endfor %}
</ul>Фильтры в шаблонах
Фильтры позволяют преобразовывать данные:
<p>{{ name|upper }}</p> # АННА
<p>{{ name|lower }}</p> # анна
<p>{{ name|capitalize }}</p> # Анна
<p>{{ name|length }}</p> # 4
<p>{{ price|round(2) }}</p> # 10.99
<p>{{ text|truncate(20) }}</p> # Обрезает до 20 символовНаследование шаблонов
Наследование позволяет создать базовый шаблон и переиспользовать его.
Базовый шаблон templates/base.html:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Мой сайт{% endblock %}</title>
</head>
<body>
<header>
<h1>Мой сайт</h1>
<nav>
<a href="/">Главная</a>
<a href="/about">О нас</a>
</nav>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>© 2026 Мой сайт</p>
</footer>
</body>
</html>Дочерний шаблон templates/index.html:
{% extends "base.html" %}
{% block title %}Главная страница{% endblock %}
{% block content %}
<h2>Добро пожаловать!</h2>
<p>Это главная страница сайта.</p>
{% endblock %}Совет: Наследование помогает избежать дублирования кода. Все изменения вносятся в базовый шаблон и автоматически применяются ко всем страницам.
Полный пример
app.py:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/about')
def about():
return render_template('about.html')
@app.route('/users')
def users():
users = [
{'name': 'Анна', 'age': 25},
{'name': 'Иван', 'age': 30},
{'name': 'Петр', 'age': 20}
]
return render_template('users.html', users=users)
if __name__ == '__main__':
app.run(debug=True)templates/base.html — базовый шаблон.
templates/index.html:
{% extends "base.html" %}
{% block title %}Главная{% endblock %}
{% block content %}
<h2>Привет, мир!</h2>
<p>Это главная страница моего сайта на Flask.</p>
{% endblock %}
[/code]templates/about.html:
{% extends "base.html" %}
{% block title %}О нас{% endblock %}
{% block content %}
<h2>О нас</h2>
<p>Мы создаём сайты на Flask.</p>
{% endblock %}templates/users.html:
{% extends "base.html" %}
{% block title %}Пользователи{% endblock %}
{% block content %}
<h2>Список пользователей</h2>
<ul>
{% for user in users %}
<li>{{ user.name }} ({{ user.age }} лет)</li>
{% endfor %}
</ul>
{% endblock %}Задачи для закрепления
Задача 1. Создай шаблон для главной страницы с приветствием.
Задача 2. Передай список из трёх товаров и выведи их в таблицу.
Задача 3. Добавь условие, которое показывает «В наличии» или «Нет в наличии».
Задача 4. Добавь базовый шаблон с шапкой и подвалом.
Задача 5. Используй фильтр |upper для вывода имени в верхнем регистре.
Ответы:
Задача 1.
@app.route('/')
def index():
return render_template('index.html', name='Анна')Задача 2.
@app.route('/products')
def products():
products = [
{'name': 'Ноутбук', 'price': 1000, 'in_stock': True},
{'name': 'Телефон', 'price': 500, 'in_stock': True},
{'name': 'Наушники', 'price': 100, 'in_stock': False}
]
return render_template('products.html', products=products)Задача 3.
<table>
<tr>
<th>Товар</th>
<th>Цена</th>
<th>Наличие</th>
</tr>
{% for product in products %}
<tr>
<td>{{ product.name }}</td>
<td>{{ product.price }}$</td>
<td>
{% if product.in_stock %}
✅ В наличии
{% else %}
❌ Нет в наличии
{% endif %}
</td>
</tr>
{% endfor %}
</table>Задача 4.
{% extends "base.html" %}Задача 5.
<h1>{{ name|upper }}</h1>Нюансы и подводные камни
Папка templates
Flask ищет шаблоны в папке templates по умолчанию.
app = Flask(__name__)Если нужно изменить путь:
app = Flask(__name__, template_folder='my_templates')Автоэкранирование
Jinja2 автоматически экранирует HTML для предотвращения XSS-атак.
# Безопасно
{{ user_input }}
# Отключаем экранирование (используй с осторожностью)
{{ user_input|safe }}Использование Python-кода
В шаблонах нельзя выполнять Python-код напрямую. Только переменные, фильтры и теги.
Частые ошибки и как их избежать
Ошибка 1: Неправильный путь к папке templates
Проверь, что папка templates находится рядом с app.py.
Ошибка 2: Забыл передать переменную в render_template()
Проверь, что все переменные переданы в шаблон.
Ошибка 3: Неправильный синтаксис Jinja2
Используй {{ }} для переменных, {% %} для логики.
Шпаргалка
| Что нужно | Как пишется |
|---|---|
| Переменная | {{ variable }} |
| Условие | {% if condition %} |
| Цикл | {% for item in items %} |
| Комментарий | {# комментарий #} |
| Блок | {% block name %}{% endblock %} |
| Наследование | {% extends "base.html" %} |
| Фильтр | {{ name|upper }} |
| Безопасный вывод | {{ html|safe }} |
Заключение
Сегодня мы:
- Настроили папку
templates - Научились рендерить шаблоны
- Передавали данные в шаблоны
- Использовали циклы и условия
- Наследовали шаблоны







