Найти в Дзене
AERONYTE

Представления, маршруты, шаблоны и стили в Django 5: пошаговое руководство с примерами

Эта статья подготовлена по мотивам книги «Django 5 By Example» (автор: Antonio Melé, издательство: Packt Publishing, 5-е издание, ISBN: 9781805122340). Статья не является официальным переводом книги и не копирует оригинальный текст. Все материалы в публикации — это мои личные переработки, пояснения, примеры и улучшения, сделанные с целью образовательной поддержки русскоязычного сообщества разработчиков. Примеры кода, использованные в статье, основаны на открытом репозитории книги и распространяются по лицензии MIT, допускающей свободное использование с указанием авторства. Все права на оригинальное содержание принадлежат автору книги и издательству Packt Publishing. 📖 Оригинальная книга доступна на официальном сайте:
https://www.packtpub.com/en-us/product/django-5-by-example-9781805122340 Эта статья явлется продолжением статьи Создание Блога на Django 5, PostgreSQL 16 с полнотекстовым поиском. В этот раз мы пройдем путь от настройки представлений (views), маршрутов (urls) и шаблонов
Оглавление

⚠️ Дисклеймер

Эта статья подготовлена по мотивам книги «Django 5 By Example» (автор: Antonio Melé, издательство: Packt Publishing, 5-е издание, ISBN: 9781805122340).

Статья не является официальным переводом книги и не копирует оригинальный текст. Все материалы в публикации — это мои личные переработки, пояснения, примеры и улучшения, сделанные с целью образовательной поддержки русскоязычного сообщества разработчиков.

Примеры кода, использованные в статье, основаны на открытом репозитории книги и распространяются по лицензии MIT, допускающей свободное использование с указанием авторства.

Все права на оригинальное содержание принадлежат автору книги и издательству Packt Publishing.

📖 Оригинальная книга доступна на официальном сайте:

https://www.packtpub.com/en-us/product/django-5-by-example-9781805122340

О чём эта статья и чем она будет полезна?

Эта статья явлется продолжением статьи Создание Блога на Django 5, PostgreSQL 16 с полнотекстовым поиском.

В этот раз мы пройдем путь от настройки представлений (views), маршрутов (urls) и шаблонов (templates) до подключения тёмной темы в стиле Киберпанк и адаптивного дизайна в духе Яндекс.Дзен.

Статья будет полезна:

  • новичкам, которые хотят понять, как устроен MVC-подход в Django на практике;
  • джунам и мидлам, желающим закрепить навыки создания кастомных представлений и шаблонов;
  • разработчикам, стремящимся быстро задать профессиональный визуальный стиль без глубоких знаний CSS.

В процессе вы:

  • создадите список и детальное представление постов,
  • научитесь правильно подключать URL-маршруты через пространства имён,
  • организуете шаблоны по best practices (base.html + наследование),
  • создадите команду manage.py для управления публикациями,
  • и добавите адаптивную тёмную тему — сначала яркую (киберпанк), затем минималистичную (в стиле Дзен).

Введение

Зачем нужны представления в Django?

Теперь, когда вы понимаете, как использовать ORM, вы готовы приступить к созданию представлений (views) для блога.

Представление в Django — это обычная Python‑функция, которая принимает веб‑запрос и возвращает веб‑ответ. Вся логика, необходимая для формирования нужного ответа, реализуется внутри представления.

Как связаны представления, маршруты и шаблоны?

Сначала вы создаете представления приложения, затем определяете шаблоны URL для каждого представления, и в конце — создаете HTML‑шаблоны для отображения данных, которые формируются представлениями. Каждое представление будет рендерить шаблон, передавать ему переменные и возвращать HTTP‑ответ с отрендеренным результатом.

Шаг 1. Создание представлений

Представление для списка постов (post_list)

Давайте начнём с создания представления, которое будет отображать список постов. Отредактируйте файл views.py в приложении blog, чтобы он выглядел следующим образом:

-2

Это — наше первое представление в Django.

Функция post_list принимает единственный аргумент — объект запроса request. Этот параметр обязателен для всех представлений.

В этом представлении мы получаем все посты со статусом PUBLISHED с помощью менеджера published, который мы ранее создали.

Затем мы используем вспомогательную функцию render(), предоставленную Django, чтобы отрендерить список постов с использованием заданного шаблона.

Функция render() принимает три аргумента:

  1. Объект request,
  2. Путь к HTML-шаблону,
  3. Словарь с переменными контекста, которые будут переданы в шаблон.

Функция возвращает объект HttpResponse с отрендеренным текстом (обычно — HTML-кодом).

Функция render() автоматически учитывает контекст запроса, поэтому все переменные, определённые контекстными процессорами шаблонов, будут доступны в шаблоне.

Контекстные процессоры — это просто функции, которые добавляют переменные в контекст.

Представление для одного поста (post_detail)

Теперь давайте создадим второе представление — для детального отображения одного поста. Добавьте в views.py следующую функцию:

-3

Это представление post_detail. Оно принимает аргумент id — идентификатор поста.

Внутри функции мы пытаемся получить объект Post с указанным id через метод get() менеджера published.

Если пост не найден и выбрасывается исключение DoesNotExist, мы вызываем исключение Http404, чтобы вернуть HTTP-ответ с ошибкой 404.

Мы снова используем функцию render() для отображения найденного поста с помощью соответствующего шаблона.

Как работает get_object_or_404?

Django предоставляет удобную функцию - get_object_or_404, которая вызывает метод get() на переданном менеджере модели и автоматически выбрасывает исключение Http404, если объект не найден, вместо стандартного DoesNotExist.

Отредактируйте файл views.py, чтобы импортировать get_object_or_404 и изменить представление post_detail следующим образом.

-4

В обновлённом представлении post_detail мы используем функцию get_object_or_404() для получения нужного поста.

Эта функция возвращает объект, соответствующий переданным параметрам, либо вызывает исключение Http404, если такой объект не найден.

В файле blog/views.py должен быть следующий код:

-5

Шаг 2. Настройка маршрутов (URL)

URL-шаблоны (URL patterns) позволяют связать адреса (URL) с определёнными представлениями.

Каждый URL-шаблон состоит из трёх компонентов:

  1. строкового паттерна (маршрута),
  2. вызываемого представления (view),
  3. (опционально) имени, по которому можно ссылаться на этот маршрут во всём проекте.

Django проходит по каждому шаблону URL сверху вниз и останавливается на первом совпадении с входящим URL.

После этого он импортирует соответствующее представление и вызывает его, передавая в него объект HttpRequest и аргументы маршрута (позиционные или именованные).

Создание urls.py в приложении blog

Создайте файл urls.py в директории приложения blog и добавьте в него следующий код:

-6

Что здесь происходит:

  • app_name = 'blog' — задаёт пространство имён (namespace) для приложения. Это критически важно, если в проекте несколько приложений с однотипными маршрутами. С помощью app_name можно ссылаться на маршруты по схеме blog:post_list и blog:post_detail.
  • Первый маршрут — это корень (''), он ссылается на представление post_list.
  • Второй маршрут — это '<int:id>/'. Он принимает один аргумент id и передаёт его в представление post_detail.

Django использует конвертеры маршрута (path converters) в фигурных скобках, чтобы преобразовывать значения из строки в тип данных:

  • <int:id> — целое число;
  • <slug:post> — "slug" строка (буквы, цифры, дефисы, подчёркивания);
  • <str:name> — строка;
  • <uuid:uuid> — UUID;
  • <path:some_path> — путь с /.

Полный список доступен в документации:
📎
https://docs.djangoproject.com/en/5.0/topics/http/urls/#path-converters

Если базовых конвертеров path() недостаточно — можно использовать re_path() и регулярные выражения. Подробнее:
📎
https://docs.djangoproject.com/en/5.0/ref/urls/#django.urls.re_path
📎
https://docs.python.org/3/howto/regex.html

Совет от сеньора: Всегда создавай отдельный urls.py в каждом приложении — это делает его переиспользуемым и изолированным. Особенно важно в больших проектах и при публикации приложения как Django-пакета.

Подключение маршрутов blog в корневом mysite/urls.py

Теперь необходимо включить маршруты blog/urls.py из приложения blog в корневой маршрут mysite/urls.py проекта.

Откройте mysite/urls.py и измените его следующим образом:

-7

Разбор:

  • include('blog.urls', namespace='blog') — встраивает маршруты из blog/urls.py, и все они теперь будут доступны по префиксу /blog/.
  • namespace='blog' — связывает пространство имён с этим блоком маршрутов. Это важно для надёжной ссылки на маршруты в шаблонах и функциях reverse().

Использование пространств имён (app_name, namespace)

Теперь можно использовать маршруты по их имени, через пространство имён:

-8

Или в Python-коде (например, редирект):

-9

Если кратко, настройка маршрутов — это архитектурная основа вашего проекта. Используя имена и пространства имён (app_name, name), вы обеспечиваете стабильную и удобную навигацию по проекту.

Шаг 3. Создание шаблонов

Мы уже создали представления и URL-шаблоны для блога.

URL-шаблоны связывают URL с представлениями, а представления определяют, какие данные возвращать пользователю.

Шаблоны (templates) — отвечают за то, как эти данные отображаются. Обычно они пишутся на HTML с использованием шаблонного языка Django.

📎 Подробнее о шаблонном языке Django:
https://docs.djangoproject.com/en/5.0/ref/templates/language/

Структура шаблонов в приложении blog

Добавим в наше приложение blog следующие каталоги и файлы:

-10

Это будет структура шаблонов для блога.

  • base.html — базовый шаблон сайта: включает общую HTML-структуру, общие стили, и делит страницу на основную часть и сайдбар.
  • post/list.html — шаблон для отображения списка постов.
  • post/detail.html — шаблон для отображения отдельного поста.

Оба шаблона list.html и detail.html наследуются от base.html, чтобы повторно использовать общую структуру сайта.

Как работает шаблонный язык Django

Django предоставляет мощный шаблонный язык, с помощью которого можно управлять отображением данных. Он состоит из трёх основных элементов:

  • Шаблонные теги (template tags) — управляют логикой рендеринга и имеют вид: {% tag %}

Пример:

{% for post in posts %}, {% if user.is_authenticated %}
  • Шаблонные переменные (template variables) — отображают значения и имеют вид: {{ variable }}

Пример:

{{ post.title }}, {{ user.username }}
  • Шаблонные фильтры (template filters) — позволяют модифицировать значения перед отображением.
    Вид: {{ variable|filter }}

Пример:

{{ post.body|truncatewords:30 }}, {{ publish|date:"d.m.Y" }}

Полный список встроенных тегов и фильтров:
📎
https://docs.djangoproject.com/en/5.0/ref/templates/builtins/

Совет от сеньора:
Пишите шаблоны так, чтобы повторяемая структура (хедер, футер, меню) находилась в base.html, а всё специфичное для страниц подключалось блоками ({% block content %} и т.д.) — это делает шаблоны поддерживаемыми и переиспользуемыми.

Базовый шаблон base.html: зачем он нужен?

Откройте файл base.html и добавьте в него следующий код:

-11

Подробное объяснение на уровне senior

{% load static %}

Эта строка сообщает Django, что нужно загрузить теги шаблонов для работы со статикой. Они предоставляются встроенным приложением django.contrib.staticfiles, которое обязательно должно быть добавлено в список INSTALLED_APPS.

После этого можно использовать тег {% static %} для подключения CSS, JS, изображений и других файлов.

Пример:

-12

Здесь подключается CSS-файл, находящийся по пути:

-13

Использование {% block %}

Шаблон использует два блока:

{% block title %}{% endblock %}
{% block title %}{% endblock %}

{% block content %}{% endblock %}
{% block content %}{% endblock %}

Блоки позволяют шаблонам-наследникам вставлять свой контент в нужные места, переопределяя содержимое этих блоков. Это базовый механизм наследования шаблонов в Django.

Например, шаблон list.html будет выглядеть так:

-16

Советы по best practices

  • Храните всю повторяющуюся разметку (head, footer, menu, sidebar) в base.html.
  • Используйте блочные теги {% block %} для участков, которые будут кастомизироваться в дочерних шаблонах.
  • Всегда подключайте статику через {% static %} — это гарантирует, что пути будут корректными даже при использовании CDN, collectstatic, или в продакшн-окружении.
  • Проверяйте, что STATICFILES_DIRS и STATIC_URL корректно настроены в settings.py.

Шаблон base.html — каркас всего блога. Он формирует основу визуального оформления и позволяет дочерним шаблонам гибко вставлять свои данные без дублирования структуры.

Шаблон списка постов post/list.html

Откройте файл post/list.html и вставьте в него следующий код:

-17

Подробный разбор шаблона на уровне senior

{% extends "blog/base.html" %}

Этот тег сообщает Django, что данный шаблон наследуется от базового шаблона base.html, расположенного по пути blog/base.html.

Он автоматически подтянет структуру base.html, а в блоки title и content будет вставлено содержимое, определённое в этом дочернем шаблоне.

{% block title %} и {% block content %}

Мы переопределяем два блока из base.html:

  • В блок title вставляется заголовок страницы "Блог ALEXPROIT".
  • В блок content — весь основной контент: список постов.

{% for post in posts %}

Перебираем все посты, переданные из представления post_list, и для каждого выводим:

Заголовок, обёрнутый в ссылку на детальную страницу поста:

-18

Тег {% url %} для динамической генерации URL

<a href="{% url 'blog:post_detail' post.id %}">{{ post.title }}</a>
  • Здесь используется тег {% url %} для динамической генерации URL по имени маршрута.

    'blog:post_detail' — это полное имя маршрута, с пространством имён blog (указан в app_name), и именем post_detail.

    В аргументах передаётся post.id, необходимый для построения URL.
⚠️ Важно: Никогда не прописывайте URL жёстко (типа /blog/42/). Всегда используйте {% url %} — это делает код надёжным и нечувствительным к изменению маршрутов.

Фильтры шаблонов: truncatewords и linebreaks

{{ post.body|truncatewords:30|linebreaks }}
  • truncatewords:30 — сокращает текст до 30 слов.
  • linebreaks — преобразует переносы строк (\n) в HTML-теги <br> и <p>.

Можно комбинировать любое количество фильтров — каждый применяется к результату предыдущего.

Best practices:

  • Делайте шаблоны максимально декларативными, используя фильтры и теги Django — это упрощает поддержку.
  • Используйте truncatewords, чтобы не перегружать страницу длинными текстами.
  • Следите, чтобы шаблоны были чистыми: без бизнес-логики и условий, которые лучше реализовать в представлении.
  • Используйте {% empty %} внутри {% for %} для обработки случая, когда список пуст.

Почему стоит использовать {% empty %}?

{% empty %} внутри {% for %} для нашего блога

В файл post/list.html добавим {% empty %} внутри {% for %} для нашего блога.

-19

Файл post/list.html целиком будет иметь вид:

-20

Почему стоит добавить {% empty %}

Польза:

  1. Пользовательский опыт: посетитель не будет видеть пустую страницу.
  2. Явное поведение: вы чётко контролируете, что покажется, если posts пуст.
  3. Удобство отладки: если данные не пришли, вы это сразу увидите в браузере, а не будете думать "почему всё пусто".

Вывод

Блок {% empty %} желательно использовать всегда, когда работаешь с циклом for, особенно в представлениях, отображающих контент из базы данных. Это улучшает UX и делает шаблон более надёжным.

Шаг 4. Отладка и запуск блога

Чтобы проверить работу блога, выполните несколько завершающих шагов:

Как проставить статус "Опубликовано"

Выполните команду для запуска тестового веб сервера Django%

python manage.py runserver

Зайдите в админку сайта по ссылке:

http://127.0.0.1:8000/admin/

и проставьте у постов, которые должны быть опубликованы, статус "Опубликовано".

-21

Затем создайте несколько новых постов — также со статусом "Опубликовано". Это необходимо, чтобы они отображались в публичной части сайта, так как представления фильтруют посты по этому статусу:

Post.published.all()

Как проверить отображение постов в браузере?

Откройте в браузере адрес:

http://127.0.0.1:8000/blog/

Результат:

-22

Если всё сделано правильно, вы увидите страницу, на которой отображаются опубликованные посты.

Каждый заголовок — это кликабельная ссылка, ведущая на страницу поста.

Шаг 5. Управление публикацией через manage.py

Как создать кастомную команду unpublish_all_posts

Для проведения экспериментов создадим manage команду, которая автоматически будет снимать с публикации все посты блога.

Для этого создадим файл: blog/management/commands/unpublish_all_posts.py

Добавьте содержимое файла unpublish_all_posts.py:

-23

⚠️ Важно: рядом должен быть пустой __init__.py файл в каждой папке (management/, commands/), чтобы Django их распознал как модули.

Проверка количества опубликованных и неопубликованных постов

Запустите команду:

python manage.py unpublish_all_posts

Результат:

-24

Выполните команду:

python manage.py shell_plus --print-sql

Проверим, сколько опубликованных постов сейчас в базе.

Выполните запрос:

>>> from blog.models import Post
>>> Post.published.count()

Результат:

-25

Опубликованных постов в базе нет - 0 шт.

Проверим сколько в базе неопубликованных постов:

Post.objects.filter(status=Post.Status.DRAFT).count()

Реузультат:

-26

Запустим тестовый сервер и проверим как будет выглядеть список постов.

python manage.py runserver

Перейдем по ссылке:

http://127.0.0.1:8000/blog/

Результат:

-27

Сделаем так чтобы наш sidebar блок был сверху, так как когда постов много его не видно.

Изменим код файла base.html:

-28

Теперь наш блок sidebar всегда будет сверху - на виду.

-29

Шаблон отдельного поста post/detail.html

Создадим шаблон для отображения детальной страницы поста.

Для этого откройте файл post/detail.html и вставьте в него следующий код:

-30

Подробный разбор шаблона на уровне senior

{% extends "blog/base.html" %}

Этот шаблон наследуется от базового — base.html, который задаёт общую структуру страницы (HTML-обёртка, стили, сайдбар и т.п.).

Наследование позволяет избежать дублирования кода и повысить переиспользуемость.

Блоки title и content

{% block title %} — устанавливает HTML‑заголовок страницы (<title> в <head>). Он выводится как название вкладки в браузере.

{% block title %}{{ post.title }}{% endblock %}

{% block content %} — основной контент страницы:

<h1>{{ post.title }}</h1>
<p class="date">дата публикации:{{ post.publish }}, автор: {{ post.author }}</p>
{{ post.body|linebreaks }}

Здесь:

  • {{ post.title }} — заголовок поста.
  • {{ post.publish }} — дата публикации (можно дополнительно отформатировать фильтром |date:"d.m.Y").
  • {{ post.author }} — имя пользователя, связанного с постом.
  • {{ post.body|linebreaks }} — содержимое поста с автоматическим преобразованием \n в <br> и <p>.

Перейдем в админку блога и проставим статус "Опубликовано" на нескольких постах, чтобы попрактиковаться и поверить работу нашего блога.

Откроем список постов по ссылке:

http://127.0.0.1:8000/blog/

Результат:

-31

Сверху видим наш сайдбар, а ниже список опубликованных постов. Кликнем по заголовку любого поста из списка и проверим работу шаблона post/detail.html.

Результат:

-32

На скриншоте видим сверху наш сайдбар, ниже заголовок и тело поста.

Вывод - наш блог работает правильно.

Шаг 6. Улучшение UI: стиль Киберпанк

Добавление Bootstrap 5.3 и тёмной темы

Давайте добавим стили, чтобы наш блог выглядел в стиле киберпанк и был с темной темой и адаптивен для мобильных устройств.

Не будем сильно заморачиваться со стилями - воспользуемся bootsrap 5.3

Сделаем всю красоту с помощью ChatGPT.
Изучите и скопируйте промт, вставьте в чат и получите результат.

Откроем новый чат и опишем что мы хотим сделать:
Я сделал блог на Django 5, python 3.12. Блог показывает список постов и детали каждого поста. Сейчас нет стилей. Блог выглядит некраисиво.

Помоги сделать адаптивную верстку bootsrap 5.3, темную тему в стиле киберпанк.

Сейчас я загружу содержимое шаблонов. Твоя задача добавить стили по заданиювыше.

blog/base.html

{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link href="{% static "css/blog.css" %}" rel="stylesheet">
</head>
<body>
<div id="sidebar">
<h2>Блог ALEXPROIT</h2>
<p>Всем привет! Это мой блог на Django 5.</p>
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>


blog/post/list.html

{% extends "blog/base.html" %}

{% block title %}Блог ALEXPROIT{% endblock %}

{% block content %}
<h1>Блог ALEXPROIT</h1>
{% for post in posts %}
<h2>
<a href="{% url 'blog:post_detail' post.id %}">
{{ post.title }}
</a>
</h2>
<p class="date">
дата публикации: {{ post.publish }}, автор: {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% empty %}
<p>Нет доступных постов. Загляните позже!</p>
{% endfor %}
{% endblock %}

{% extends "blog/base.html" %}

{% block title %}Блог ALEXPROIT{% endblock %}

{% block content %}
<h1>Блог ALEXPROIT</h1>
{% for post in posts %}
<h2>
<a href="{% url 'blog:post_detail' post.id %}">
{{ post.title }}
</a>
</h2>
<p class="date">
дата публикации: {{ post.publish }}, автор: {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% empty %}
<p>Нет доступных постов. Загляните позже!</p>
{% endfor %}
{% endblock %}

blog/post/detail.html

{% extends "blog/base.html" %}

{% block title %}{{ post.title }}{% endblock %}

{% block content %}
<h1>{{ post.title }}</h1>
<p class="date">
дата публикации: {{ post.publish }}, автор: {{ post.author }}
</p>
{{ post.body|linebreaks }}
{% endblock %}

Выполни задание на уровне сеньор

Результат:

blog/base.html

-33

list.html

-34

detail.html

-35

blog.css

-36

Теперь перенесите обновленный код в наши файлы стилей и шаблоны и запустите тестовый сервер по адресу:

http://127.0.0.1:8000/blog/

Результат:

-37
-38

Согласитесь это хороший результат за пару минут.

Теперь уменьшим разрещение экрана и проверим адапртивность нашего блога при отображении информации на маленьких экранах.

Результат:

-39
-40
-41
-42

Как видно из скриншотов - полный адаптив.

Шаг 7. Улучшение UX: стиль Яндекс.Дзен

Почему мы перешли от Киберпанка к Дзену?

Этот стиль слишком яркий и будет мешать читать наши посты. Поэтому давайте выполним следующий короткий промт в ChatGPT:

Теперь я хочу чтобы ты сделал все тоже самое только в стиле Дзен - блог платформы от Яндекса в темной теме

Результат:

Обновление стилей и шаблонов

base.html

-43

list.html

-44

detail.html

-45

blog.css

-46

Проверка адаптивности и читаемости

Обновите код в ваших файлах шаблонов и стилей и запустите тестовый веб сервер Django.

python manage.py runserver

Перейдите по ссылке:

http://127.0.0.1:8000/blog/

Результат:

Страница со списоком постов

Шапка сайта

-47

Подвал

-48

Страница поста

-49

Как видно из скриншотов мы получили адаптивный удобный и споскойный дизайн в стиле Дзен, который позволит сконцентрировать внимание на посте и его содержании а не элементах интерфейса.

Этот дизайн мы будем использовать в дальнейшем при создании нашего приложения блог.

Вопросы, которые задают на собеседованиях

🟢 Вопросы для Junior-разработчика

  1. Что такое представление (view) в Django?
  2. Чем отличаются function-based views и class-based views?
  3. Какой аргумент обязательно принимает функция-представление?
  4. Как вернуть HTML-ответ из представления?
  5. Для чего используется функция render()?
  6. Что такое get_object_or_404() и зачем она нужна?
  7. Как передать переменные из представления в шаблон?
  8. Что делает тег {% url 'имя_маршрута' аргументы %} в шаблоне?
  9. Чем отличаются {{ переменная }} и {% тег %} в шаблонах Django?
  10. Что произойдёт, если в {% for %} не использовать {% empty %}?

🟡 Вопросы для Middle-разработчика

  1. Как работает механизм маршрутизации (path(), re_path(), include()) в Django?
  2. Зачем использовать app_name и namespace в urls.py?
  3. Как организовать маршруты в большом проекте с несколькими приложениями?
  4. В чём разница между HttpResponse, render() и redirect()?
  5. Как Django находит шаблоны при рендеринге?
  6. Какие способы передачи данных в шаблон ты знаешь, кроме контекста в render()?
  7. Как избежать дублирования кода в шаблонах?
  8. Как работает механизм наследования шаблонов в Django?
  9. Как подключать статику и медиафайлы в шаблонах?
  10. Какие фильтры шаблонов ты используешь чаще всего?

🔴 Вопросы для Senior-разработчика

  1. Как организовать структуру проекта, чтобы он был расширяемым и поддерживаемым при росте количества представлений и маршрутов?
  2. Как построить REST API на основе существующих views, не переписывая бизнес-логику?
  3. Как реализовать шаблоны с минимальным количеством логики, соблюдая Separation of Concerns?
  4. Как писать собственные template tags и фильтры в Django?
  5. Как реализовать универсальные компоненты шаблонов (например, карточку поста) для повторного использования?
  6. Как масштабировать маршрутизацию с использованием вложенных include() и пространств имён?
  7. Как обеспечить кэширование шаблонов и представлений для повышения производительности?
  8. Как настроить шаблонные контекстные процессоры и зачем это нужно?
  9. Какие подходы ты используешь для тестирования представлений и шаблонов?
  10. Как обезопасить шаблоны Django от XSS и других атак?

Заключение: чему мы научились и зачем это нужно

В этой статье мы прошли полный цикл разработки базового блога на Django 5:

  • Создали представления для списка и деталей постов,
  • Настроили маршруты с использованием пространства имён,
  • Построили гибкую систему шаблонов на основе base.html,
  • Освоили фильтрацию данных через менеджеры моделей,
  • Добавили кастомную команду управления публикациями через manage.py,
  • Оформили блог в тёмной теме с адаптивной вёрсткой, сначала в стиле киберпанк, а затем — в стиле Яндекс.Дзен.

Благодаря этому вы:

  • На практике закрепили архитектуру Django: Model → View → Template.
  • Поняли, как отделять логику отображения от бизнес-логики.
  • Получили основу для любого контентного проекта: от блога до новостного портала.
  • Познакомились с настройкой тем оформления и созданием интерфейсов, удобных для чтения.

Этот проект — отправная точка для масштабирования:

  • Добавления пагинации, поиска, тегов;
  • Подключения комментариев и авторизации;
  • Развёртывания в продакшен с помощью Docker, Nginx и PostgreSQL.

Если статья была полезной

📌 Если статья оказалась полезной — поставьте лайк или отметьте её, чтобы я понял, что такой формат стоит развивать дальше.

✍️ Напишите в комментариях, как вы обычно создаёте шаблоны и маршруты — используете class-based views или предпочитаете function-based? А может, хотите увидеть сравнение двух подходов?

📤 Если у вас в команде есть те, кто только начинает изучать Django — поделись с ними ссылкой на статью. Это сэкономит им кучу времени и поможет сразу строить проект по best practices.

📚 Подписывайтесь, чтобы не пропустить следующие разборы: расскажу про пагинацию, теги, систему комментариев, авторизацию и деплой Django-проекта в прод с Docker, Nginx и PostgreSQL.

До встречи в следующих публикациях!