Контекст шаблона в Django: что нужно знать заранее
Разбираемся, откуда в HTML-шаблоне Django берутся переменные, как передать их из view и почему пустая страница чаще всего означает опечатку в ключе словаря, а не ошибку рендеринга.

К концу этого текста вы поймёте, как данные из вашей Python-функции попадают в HTML-шаблон Django, как их туда положить и почему на странице иногда ничего не выводится, хотя ошибки нет. На чтение и первые эксперименты уйдёт около 20 минут. Написано для Django 5.x, но принцип одинаков начиная с версии 1.x — менялись детали, не суть.
Контекст — это данные, которые view передаёт шаблону: словарь, где ключи становятся именами переменных внутри HTML. Без понимания, как этот словарь устроен, вы будете гадать, почему {{ user.name }} выводит пустоту, а {{ items }} печатает что-то вроде <QuerySet [...]>.
Что нужно иметь до начала
- Установленный Django 5.x (
pip install django) и созданный проект. - Хотя бы одно приложение с рабочим
urls.py, который ведёт на вашу view. - Папку
templates, подключённую в настройках. Проверьте вsettings.py: в блокеTEMPLATESу бэкендаdjango.template.backends.django.DjangoTemplatesдолжно быть'APP_DIRS': True— тогда Django ищет шаблоны в папкеtemplatesвнутри каждого приложения.
Если APP_DIRS стоит False и список DIRS пуст, шаблоны не найдутся вообще — с этого спотыкается почти каждый новичок.
Как контекст попадает в шаблон
Идея простая: view собирает словарь и отдаёт его функции рендеринга. Ключи словаря становятся именами переменных в шаблоне. Разберём на минимальном примере.
Шаг 1. Напишите view с контекстом
Откройте views.py вашего приложения и добавьте функцию:
# views.py (Django 5.x)
from django.shortcuts import render
def profile_view(request):
# словарь и есть контекст: ключи станут переменными в шаблоне
context = {
"username": "Мария",
"orders_count": 3,
"is_premium": True,
}
return render(request, "profile.html", context)
Функция render берёт запрос, имя шаблона и словарь контекста, собирает готовый HTML и возвращает HttpResponse. Проверка: если импорт и объявление на месте, при запуске сервера ошибок в консоли не будет.
Шаг 2. Создайте шаблон
В папке templates вашего приложения создайте файл profile.html:
<h1>Привет, {{ username }}</h1>
<p>Заказов: {{ orders_count }}</p>
{% if is_premium %}
<p>У вас премиум-доступ</p>
{% endif %}
Двойные фигурные скобки {{ }} выводят значение переменной. Фигурная скобка с процентом {% %} — это тег: условие, цикл, подключение другого шаблона. Проверка: откройте адрес, ведущий на profile_view. В браузере должно появиться «Привет, Мария» и «Заказов: 3».
Шаг 3. Свяжите URL с view
Если страница не открывается, проверьте urls.py:
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path("profile/", views.profile_view, name="profile"),
]
Проверка: адрес /profile/ отдаёт страницу, а не ошибку 404.
Как Django ищет значение переменной
Когда шаблон встречает {{ user.name }}, Django пробует несколько способов достучаться до значения, по порядку:
- Обращение по ключу словаря:
user['name']. - Обращение к атрибуту объекта:
user.name. - Вызов метода без аргументов:
user.name()— еслиnameоказался методом, Django вызовет его сам. - Обращение по индексу списка:
items.0вернёт первый элемент.
Отсюда две важные вещи. Первая: в шаблоне нельзя вызвать метод с аргументами — {{ obj.get_price(10) }} не сработает, вынесите логику во view или в собственный тег. Вторая: точка в шаблоне значит не то же, что в Python — это универсальный оператор доступа, который сам разбирается, словарь перед ним, объект или список.
Пустая страница вместо ошибки — почти всегда не сбой рендеринга, а опечатка в имени переменной. Django по умолчанию подставляет пустую строку вместо несуществующей переменной и молчит.
Почему несуществующая переменная не роняет страницу
За это отвечает настройка string_if_invalid в опциях бэкенда шаблонов. По умолчанию она пустая, поэтому {{ nonexistent }} превращается в ничто. На время отладки можно временно задать заметное значение, чтобы опечатки бросались в глаза:
# settings.py, только для разработки
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"APP_DIRS": True,
"OPTIONS": {
"string_if_invalid": "INVALID:%s",
"context_processors": [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
],
},
},
]
Теперь вместо пустоты на странице появится INVALID:username, и вы сразу увидите, где опечатались. На проде это значение убирают.
Откуда ещё берутся переменные: контекст-процессоры
В шаблоне часто доступны переменные, которых нет в вашем словаре — например, {{ request }} или {{ user }}. Их добавляют контекст-процессоры: функции, которые Django вызывает при каждом рендеринге через render и подмешивает результат в контекст.
Список процессоров лежит в OPTIONS['context_processors']. Стандартный набор даёт request, текущего пользователя, служебные переменные для сообщений и статики. Важная деталь: контекст-процессоры работают только через RequestContext, то есть через функцию render и объект запроса. Если вы рендерите шаблон вручную без запроса, этих переменных не будет.
| Способ доступа к данным | Что попадает в шаблон | Когда использовать |
|---|---|---|
Словарь в render(request, tpl, context) | Только ваши ключи плюс контекст-процессоры | Обычный случай для функциональных view |
| Контекст-процессор | Одни и те же переменные на всех страницах | Меню, настройки сайта, текущий пользователь |
Метод get_context_data | Ваши ключи плюс данные класса | Классовые view (ListView, DetailView) |
Классовые view: тот же контекст, другой синтаксис
Если вы используете классовые представления, контекст собирает метод get_context_data. Не забудьте вызвать родительскую реализацию через super(), иначе потеряете переменные, которые класс добавляет сам (например, object_list в ListView):
# views.py (Django 5.x)
from django.views.generic import TemplateView
class ProfileView(TemplateView):
template_name = "profile.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) # базовые переменные
context["username"] = "Мария"
context["orders_count"] = 3
return context
Если не получилось
TemplateDoesNotExist at /profile/— Django не нашёл файл. Проверьте, чтоprofile.htmlлежит вtemplatesвнутри приложения иAPP_DIRSравноTrue, а имя вrenderсовпадает с именем файла посимвольно.- Страница есть, но переменная пустая — опечатка в ключе словаря или в имени в шаблоне. Включите
string_if_invalid, как показано выше, и найдёте место за секунду. Could not parse the remainder: '(10)' from 'obj.method(10)'— вы пытаетесь вызвать метод с аргументом прямо в шаблоне. Так нельзя: перенесите вычисление во view.- Вместо данных выводится
<QuerySet [...]>— вы печатаете сам QuerySet вместо перебора. Пройдите по нему циклом{% for item in items %}. {{ user }}пустой в шаблоне — не подключён процессорdjango.contrib.auth.context_processors.authили шаблон рендерится без объекта запроса.
Что делать дальше
Когда базовый контекст работает, следующий шаг — научиться преобразовывать данные прямо в шаблоне через фильтры ({{ price|floatformat:2 }}) и выносить повторяющуюся логику в собственные теги и фильтры. Автоэкранирование HTML и тег {% autoescape %} — отдельная тема, здесь мы её не трогали, но именно она защищает от XSS, поэтому загляните в неё сразу после контекста. Начните с раздела Templates в официальной документации Django для вашей версии.
Тест и проверочная: Быстрые ответы с объяснением, почему остальные варианты неверны
Спросить за 10 ₽Источники: Django documentation — The Django template language, Django documentation — render() shortcut
Частые вопросы
У меня Django 4.2, а не 5.x — примеры сработают?
Почему на странице пусто, хотя в консоли нет ошибки?
Можно ли вызвать метод с аргументами в шаблоне?
Чем контекст в render отличается от get_context_data?
Почему переменная user доступна, хотя я её не передавал?
Что будет с производительностью, если положить в контекст большой QuerySet?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.