Наследование шаблонов: extends и блоки
Без наследования шаблонов вы будете копировать шапку, меню и подвал в каждый файл. Django решает это блоками: один базовый каркас, много страниц-наследников.
Суть: базовый шаблон задаёт каркас с именованными блоками, дочерние шаблоны его расширяют через extends и переопределяют только нужные блоки. include вставляет переиспользуемые фрагменты.
Проблема дублирования
Каждая страница сайта имеет общую обвязку: <head> с метатегами, шапку с меню, подвал, подключение стилей. Копировать всё это в десятки шаблонов — путь к аду сопровождения: поменяли меню — правьте в сорока местах. Наследование шаблонов решает проблему радикально.
Базовый шаблон
Создаём base.html — каркас с «дырками», помеченными тегом {% block %}:
<!DOCTYPE html>
<html lang="ru">
<head>
<title>{% block title %}Мой сайт{% endblock %}</title>
</head>
<body>
<header>Шапка и меню</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>Подвал</footer>
</body>
</html>
Дочерний шаблон
Конкретная страница расширяет базовый через {% extends %} (это должна быть первая строка) и переопределяет только нужные блоки:
{% extends "base.html" %}
{% block title %}Список постов{% endblock %}
{% block content %}
<h1>Посты</h1>
{% for post in posts %}
<article>{{ post.title }}</article>
{% endfor %}
{% endblock %}
Шапка, подвал и весь каркас наследуются автоматически. Вы пишете только содержимое страницы.
base.html (каркас + блоки) ▲ extends │ post_list.html ── переопределяет block title и block content │ post_detail.html ── переопределяет те же блоки по-своему
include для фрагментов
Если нужно вставить переиспользуемый кусок (карточку поста, виджет), используют {% include %}: {% include "blog/_card.html" with post=post %}. Так одна карточка применяется и в списке, и на главной.
Как это работает под капотом
Движок собирает финальную страницу так: берёт каркас базового шаблона и подставляет в его блоки содержимое из дочернего, а где дочерний блок не задан — оставляет содержимое из базового. Это языко-независимая логика «слияния словарей блоков». Вот её модель:
# Попробуй сам ▶ — слияние блоков base + child
base_blocks = {
"title": "Мой сайт",
"content": "(пусто)",
"footer": "© 2026",
}
child_blocks = { # дочерний переопределяет часть
"title": "Список постов",
"content": "Здесь список из 10 постов",
}
# extends: дочерние блоки перекрывают базовые, остальное наследуется
final = {**base_blocks, **child_blocks}
print("Итоговая страница:")
for name, value in final.items():
source = "child" if name in child_blocks else "base"
print(f" [{name:8}] = {value!r:35} ({source})")
Django делает ровно это: блоки дочернего шаблона перекрывают одноимённые блоки базового, ненайденные наследуются. Можно даже дополнить родительский блок через {{ block.super }}.
Где лежат шаблоны
Django ищет шаблоны в папках templates/ внутри приложений (если включён APP_DIRS) и в путях из DIRS. Чтобы избежать конфликтов имён между приложениями, шаблоны кладут в подпапку с именем приложения: blog/templates/blog/post_list.html.
Три уровня шаблонов: приём для крупных проектов
На больших сайтах одного base.html мало: разделы (блог, магазин, личный кабинет) имеют общую обвязку сайта, но свою внутреннюю структуру. Решение — трёхуровневая иерархия. Самый верхний base.html задаёт скелет всего сайта: шапку, подвал, подключение стилей и крупные блоки. Промежуточные шаблоны вроде blog/base.html расширяют его и добавляют боковую панель раздела, оставляя блок content открытым. А конкретные страницы наследуют уже от промежуточного. Так каждый уровень отвечает за свой слой разметки, и изменение в одном месте аккуратно распространяется вниз по всей цепочке. Этот приём — прямое следствие того, что extends можно выстраивать в цепочку любой глубины: дочерний шаблон сам может быть базовым для следующего.
Частые ошибки
- Ставить {% extends %} не первой строкой. Он обязан быть в самом начале файла.
- Не класть шаблоны в подпапку приложения. Будут конфликты имён между приложениями.
- Дублировать каркас вместо наследования. Это сводит на нет всю идею.
- Забыть {% endblock %}. Блоки парные.
Best practices
- Держите один
base.htmlна проект; для разделов — промежуточные базовые шаблоны. - Выносите повторяющиеся фрагменты в частичные шаблоны и подключайте через
include. - Именуйте частичные шаблоны с подчёркиванием:
_card.html. - Используйте
{{ block.super }}, чтобы дополнять, а не затирать базовый блок.
Итоги
Наследование шаблонов убивает дублирование: базовый каркас с блоками плюс дочерние страницы, переопределяющие нужное. extends, block, include — три кита переиспользования разметки. Дальше подключим к страницам стили, скрипты и картинки — статические файлы.