Шаблоны Jinja2 в Flask

Шаблоны Jinja2 в Flask Flask

Привет! До сих пор мы возвращали HTML прямо из функций-представлений. Это удобно для маленьких примеров, но в реальных проектах HTML лучше выносить в отдельные файлы — шаблоны. В Flask для этого используется шаблонизатор Jinja2.

В этой статье мы разберём:

  • Настройку папки templates
  • Рендеринг шаблонов
  • Передачу данных в шаблоны
  • Циклы и условия в шаблонах
  • Наследование шаблонов

Что нужно знать перед началом

Для этого урока тебе понадобится:

  • Установленный 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
  • Научились рендерить шаблоны
  • Передавали данные в шаблоны
  • Использовали циклы и условия
  • Наследовали шаблоны

КВИЗ

Что дальше?

Оцените статью
IMI-DS - PYTHON LERNEN
Содержание
Оглавление ×