Шаблоны, часть 2
Проблема: повторяющийся HTML
У всех страниц сайта есть общие части: <head>, шапка с меню, подвал. Копировать их в каждый шаблон — нарушение DRY. Решение — наследование шаблонов.
Базовый шаблон
templates/base.html:
{% load static %}
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>{% block title %}Мой сайт{% endblock %}</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<nav>
<a href="{% url 'index' %}">Главная</a>
<a href="{% url 'blog:post_list' %}">Блог</a>
</nav>
<main>
{% block content %}{% endblock %}
</main>
<footer>© 2026</footer>
</body>
</html>
{% block имя %} — «дырка», которую дочерние шаблоны могут заполнить. Содержимое внутри блока в базовом шаблоне — значение по умолчанию.
Дочерний шаблон
blog/templates/blog/post_list.html:
{% extends "base.html" %}
{% block title %}Блог — {{ block.super }}{% endblock %}
{% block content %}
<h1>Все посты</h1>
{% for post in posts %}
<h2><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h2>
{% endfor %}
{% endblock %}
Правила:
{% extends %}— первый тег в файле.- Всё, что вне блоков, в дочернем шаблоне игнорируется.
{{ block.super }}вставляет содержимое блока из родителя (здесь заголовок будет «Блог — Мой сайт»).- Наследование может быть многоуровневым:
base.html→blog/base.html→blog/post_list.html.
Сайт, на котором вы учитесь, устроен так же: все страницы наследуют base.html, где есть шапка с меню и подвал.
include: переиспользуемые фрагменты
Если один и тот же кусок (например, карточка поста) нужен на разных страницах, вынесите его в отдельный файл:
{# blog/_post_card.html #}
<article class="card">
<h2>{{ post.title }}</h2>
<p>{{ post.body|truncatewords:30 }}</p>
</article>
{% for post in posts %}
{% include "blog/_post_card.html" %}
{% endfor %}
{% include "blog/_post_card.html" with post=featured_post only %}
with передаёт переменные, only — запрещает фрагменту видеть остальной контекст. Подчёркивание в имени — просто соглашение: «это фрагмент, а не страница».
Статические файлы
CSS, JavaScript, картинки оформления — статические файлы. Они лежат в папке static/ приложения (или проекта):
blog/static/blog/css/blog.css
static/css/style.css
static/img/logo.png
Настройки:
STATIC_URL = "static/"
STATICFILES_DIRS = [BASE_DIR / "static"] # общая папка проекта
STATIC_ROOT = BASE_DIR / "staticfiles" # куда collectstatic соберёт всё для продакшена
В шаблоне:
{% load static %}
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<img src="{% static 'img/logo.png' %}" alt="Логотип">
<script src="{% static 'js/app.js' %}"></script>
Тег {% static %} строит правильный адрес с учётом STATIC_URL. В режиме разработки (DEBUG = True) runserver раздаёт статику сам, а в продакшене этим займётся NGINX (модуль «Деплой»).
Тег with
Позволяет сохранить результат «дорогого» выражения в короткую переменную:
{% with total=post.comments.count %}
<p>Комментариев: {{ total }}</p>
{% endwith %}
Контекстные процессоры
Некоторые переменные доступны в любом шаблоне, хотя view их не передавала. Их добавляют контекстные процессоры из настройки TEMPLATES["OPTIONS"]["context_processors"]:
request— текущий запрос (request.path,request.GET);user— текущий пользователь (user.is_authenticated,user.username);messages— флеш-сообщения («Пост сохранён»).
Свой процессор — функция, которая принимает request и возвращает словарь:
# blog/context_processors.py
from .models import Category
def categories(request):
return {"all_categories": Category.objects.all()}
После добавления "blog.context_processors.categories" в настройки переменная all_categories будет доступна везде — удобно для меню.
Итог
- Базовый шаблон с
{% block %}, дочерние — с{% extends %}первой строкой. {% include %}— для повторяющихся фрагментов.- Статика подключается через
{% load static %}и{% static 'путь' %}. - Контекстные процессоры добавляют переменные во все шаблоны.
Практика решено 0 из 6
Где в дочернем шаблоне должен стоять тег {% extends %}?
Напишите дочерний шаблон, который наследует base.html,
задаёт блок title с текстом Блог и блок content с заголовком <h1>Все посты</h1>.
{% extends "base.html" %}
{% block title %}Блог{% endblock %}
{% block content %}
<h1>Все посты</h1>
{% endblock %}
Что делает {{ block.super }} внутри блока?
Подключите в шаблоне файл стилей css/blog.css из статических файлов.
Не забудьте загрузить библиотеку тегов static.
{% load static %}
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
Каким тегом вставить в шаблон фрагмент из файла blog/_post_card.html? Напишите тег целиком.
{% include "blog/_post_card.html" %}Какие переменные доступны в любом шаблоне благодаря стандартным контекстным процессорам?
Войдите, чтобы отмечать пройденные уроки.