Основи Дизайну для Django-проєктів¶
Архітектура користувацьких інтерфейсів у Django-застосунках
Щоб будувати масштабовані, підтримувані та зручні Django-застосунки, розробник мусить змінити мислення: не «малювати сторінки», а проєктувати системні фронтенд-архітектури. Професійний Django-інтерфейс базується на чіткому розділенні структури, представлення і даних — з активним використанням компонентів та передбачуваних інформаційних ієрархій.
Зміст¶
- 1. Дизайн-мислення та UX-принципи
- 2. Інформаційна Архітектура (IA)
- 3. Системи Компонування та Приклади
- 4. Дизайн-Системи та Філософія Bootstrap
- 5. Архітектура Django-шаблонів
- 6. Дизайн Форм та Представлення Даних
- 7. Дизайн Дашборду
- 8. Типові Помилки Початківців
- 9. Організація Великих Django-проєктів
- 10. Tailwind CSS проти Bootstrap у Django
- 11. Статичні Файли у Django
- 12. Інтеграція React з Django
- 13. Детальна Архітектура Django-шаблонів
- 14. Детальна Архітектура Crispy Forms
1. Дизайн-мислення та UX-принципи¶
«Не змушуй мене думати» (Стів Круг)¶
Головний принцип UX — «Don't make me think» (Стів Круг, класична книга про юзабіліті). Користувачі не читають сторінки — вони їх сканують, шукаючи візуальні орієнтири. Вони «задовольняються» — обирають першу прийнятну опцію, а не аналізують усі можливі варіанти.
Твоя архітектура повинна втілювати ключові UX-характеристики: Корисна, Зручна, Знаходима, Довірена, Бажана, Доступна, Цінна.
Практичні наслідки: - Кожна сторінка має мати одну очевидну дію - Клікабельні елементи мають виглядати клікабельними - Назви кнопок: «Зберегти нотатку», а не «ОК» - Якщо зареєстрований користувач опиняється на сторінці входу — перенаправ його автоматично
CRAP-принципи дизайну¶
CRAP — абревіатура чотирьох фундаментальних принципів дизайну, які описала Робін Вільямс у книзі «Дизайн для не-дизайнерів»:
| Принцип | Опис |
|---|---|
| C — Proximity (Близькість) | Пов'язані елементи групуються разом. Більше простору між групами, менше всередині |
| R — Alignment (Вирівнювання) | Кожен елемент пов'язаний з іншими. Уникай розміщення «на вічко» |
| A — Repetition (Повторюваність) | Візуальні елементи повторюються по всьому дизайну — колір, шрифт, форма, кнопки |
| P — Contrast (Контраст) | Якщо два елементи не однакові — зроби їх зовсім різними, щоб уникнути плутанини |
Узгодженість та Конвенції¶
Стандартизовані паттерни (конвенції) знижують когнітивне навантаження. Якщо ти використовуєш стандартний кошик або іконку профілю — користувачі миттєво розуміють функцію без пояснень.
Запобігання помилкам та Зворотній зв'язок¶
Хороший інтерфейс «толерантний до помилок». Він обмежує можливість зробити щось неправильне (наприклад, дозволяє вводити лише цифри у поле кредитної картки) і надає негайний, чіткий зворотній зв'язок після кожної дії.
Простота та Відкритість¶
Завжди починай проєктування з основної функції, а не з оточуючої оболонки. Встанови чітку візуальну ієрархію — найважливіші елементи мають бути найпомітнішими, природно спрямовуючи погляд користувача.
Візуальна ієрархія та Вага¶
Не кожен елемент може бути «важливим». Якщо все кричить — нічого не чути. Будуй ієрархію через: - Розмір: великий → малий - Колір: яскравий → приглушений - Жирність: Bold → Regular → Light - Позиція: верх-ліво притягує увагу першим - Пробіл: ізольований елемент сприймається важливіше
Типографіка на Екрані¶
- Основний текст: 16px мінімум (менше стомлює очі)
- Міжрядковий інтервал: 1.5–1.6 для читабельності
- Довжина рядка: 45–75 символів в ідеалі (ні занадто вузько, ні занадто широко)
- Максимум 2–3 шрифти в одному дизайні
- Bootstrap-шкала:
.fs-1(2.5rem) →.fs-6(1rem)
2. Інформаційна Архітектура (IA)¶
Інформаційна архітектура — структурне проєктування спільних інформаційних середовищ застосунку, що балансує бізнес-цілі, потреби користувачів та зміст.
Ієрархія Сторінок¶
Застосунки використовують архітектуру «зверху-вниз» (головна сторінка передбачає основні потреби) та «знизу-вгору» (користувачі переходять безпосередньо з глибоких посилань або результатів пошуку).
Постійна Навігація¶
Глобальна навігація має залишатися на одному місці на кожній сторінці — це створює відчуття «де я знаходжуся». Вона має містити: - Логотип (ідентифікатор сайту) - Основні розділи (головні посилання) - Утиліти (Допомога, Вхід) - Пошук
Навігаційні «хлібні крихти»¶
Для глибоких застосунків «хлібні крихти» показують шлях від головної сторінки до поточного місця, надаючи очевидний спосіб повернутися вгору по ієрархії.
graph TD
A[Глобальна / Постійна Навігація] --> B[Головна / Дашборд]
A --> C[Утиліти: Профіль, Налаштування]
A --> D[Пошук]
B --> E[Розділи: CRM, Звіти тощо]
E --> F[Підрозділи / Деталі]
F -.->|Хлібні крихти| E
3. Системи Компонування та Приклади¶
Професійні веб-застосунки як правило використовують секційне компонування — як пульт управління з окремими функціональними фреймами.
Адмін-панелі та Дашборди¶
Зазвичай використовують фіксований сайдбар для первинної навігації, верхній хедер для утиліт (пошук, профіль) та плавну контентну область.
SaaS та CRM¶
Покладаються на адаптивні грід-системи, де складні дані представлені в основній контентній зоні, з переходом на одноколонковий вигляд на мобільних пристроях.
E-commerce та Блоги¶
Зазвичай використовують верхню навігацію, секцію-герой для ціннісної пропозиції та грід карток для товарів або статей.
graph TD
subgraph Архітектура Компонування
H[Хедер: Логотип, Пошук, Утиліти]
S[Сайдбар: Основна Навігація]
C[Контентна Область: Динамічні Вью]
F[Футер: Допоміжні Посилання]
H --- S
S --- C
C --- F
end
4. Дизайн-Системи та Філософія Bootstrap¶
Фронтенд-фреймворки на кшталт Bootstrap існують як шар абстракції для стандартизації дизайну, усунення хаосу кастомного CSS та прискорення створення інтерфейсів.
Обмеження Вибору¶
Дизайн-система обмежує твої варіанти (наприклад, конкретні розміри шрифтів, визначена шкала відступів та палітра кольорів). Це запобігає «паралічу вибору» і гарантує узгодженість. Замість того, щоб гадати між 120px і 125px — ти використовуєш попередньо визначену шкалу відступів на базі 16px.
Грід-Системи¶
Побудовані на 12-колоночній мобільно-орієнтованій flexbox-системі: - Контейнери обмежують ширину та центрують контент - Рядки (Row) слугують обгортками з негативними відступами - Колонки (Col) визначають відсоткову ширину
Утилітарні Класи¶
Класи для відступів (m-3), падінгів (p-4) та відображення (d-none, d-md-block) дозволяють змінювати рендеринг та адаптивну поведінку прямо в HTML без написання кастомного CSS.
Готові Компоненти¶
Елементи як кнопки, картки та сповіщення — це заздалегідь визначені абстракції. Комбінуючи ці компоненти, ти швидко створюєш складний UI без дублювання.
5. Архітектура Django-шаблонів¶
Дизайн-системи ідеально відображаються на систему наслідування шаблонів Django. Розбиваючи UI на блоки — ти дотримуєшся принципу DRY (Don't Repeat Yourself).
base.html— головна оболонка: структура<html>,<head>(CSS/JS), постійна навігація, футер.- Наслідування шаблонів: дочірні шаблони
{% extends 'base.html' %}вставляють конкретний UI у{% block content %}. - Партіали/Компоненти: дрібні UI-елементи (KPI-картка, меню, сповіщення) зберігаються у
components/і підключаються через{% include 'components/card.html' with title="Користувачі" %}.
graph TD
A["base.html<br>Глобальна Оболонка, Head, Footer"] --> B["layouts/dashboard.html<br>Сайдбар + Топбар"]
B --> C["notes_app/note_list.html<br>Грід нотаток"]
B --> D["notes_app/note_form.html<br>Форма"]
C -.-> E["components/empty_state.html"]
C -.-> F["components/pagination.html"]
C -.-> G["components/confirm_modal.html"]
D -.-> H["crispy_forms FormHelper + Layout"]
3-Рівнева Ієрархія Шаблонів (Паттерн SaaS-Дашборду)¶
templates/
├── base.html ← HTML5 оболонка, Bootstrap CDN, слоти {% block %}
├── layouts/
│ ├── dashboard.html ← base + сайдбар + топбар (extends base.html)
│ ├── auth.html ← base + центрована картка (логін/реєстрація)
│ └── landing.html ← base + маркетингова навігація
├── components/
│ ├── pagination.html ← Bootstrap-пагінація для повторного використання
│ ├── empty_state.html ← «Ще немає елементів» з CTA
│ └── confirm_modal.html ← Діалог підтвердження видалення
└── notes_app/
├── note_list.html ← extends layouts/dashboard.html
├── note_form.html ← {% crispy form %} — ОДИН ТЕГ!
└── note_detail.html ← extends layouts/dashboard.html
6. Дизайн Форм та Представлення Даних¶
Візуальна Ієрархія Форм¶
Форми мають чітко передавати зв'язки між елементами. Уникай надмірної залежності від семантичних HTML-заголовків (<h1>, <h2>), якщо вони візуально перекривають зміст форми. Відокремлюй візуальну ієрархію від документальної.
Підписи та Зворотній Зв'язок¶
Не приховуй підписи полів і не покладайся лише на placeholder-и — це шкодить доступності. Форми мають надавати негайний зворотній зв'язок через кольорові стани (зелений — успіх, червоний — помилка) та чіткий допоміжний текст.
Помилки форм у Bootstrap: Django автоматично додає CSS-клас is-invalid до полів з помилками — crispy-forms підключає це автоматично.
Три Рівні Рендерингу Форм у Django¶
| Підхід | Код у Шаблоні | Рядків | Результат |
|---|---|---|---|
| Чистий Django | {{ form.as_p }} |
1 | Без стилів |
| Ручний Bootstrap | <div class="mb-3">... для кожного поля |
60+ | Bootstrap-стиль |
django-bootstrap5 |
{% bootstrap_form form %} |
1 | Bootstrap-стиль |
| Crispy Forms | {% crispy form %} |
1 | Bootstrap + власне компонування |
Таблиці¶
Для представлення даних використовуй .table-responsive, щоб уникнути горизонтального прокручування на мобільних. Підвищуй читабельність через контекстні класи (.table-striped, .table-hover).
7. Дизайн Дашборду¶
Дашборди мають перетворювати складні дані на зручний для перегляду формат.
Організація Інформації¶
Дашборди часто використовують секційне компонування — навігація, фільтри та легенди розміщені в бічних панелях.
KPI та Графіки¶
Ключові метрики розміщуються зверху (компонент-картка). Обирай правильний тип графіку (кругова діаграма, стовпчик, рядок, точки) залежно від потреби порівняння (часовий ряд, кореляція, елемент).
Порожні Стани (Empty States)¶
Не ігноруй порожні стани. Коли користувач вперше відкриває CRM і даних немає — використай порожній стан з чітким Заклик до Дії (CTA): «Додати перший контакт» замість порожньої або зламаної таблиці.
graph LR
A[Користувач відкриває застосунок] --> B{Є дані?}
B -->|Ні| C[Порожній Стан<br>+ Кнопка CTA]
B -->|Так| D[Дашборд з<br>KPI-картками + Таблицею]
C -->|Натискає CTA| E[Створює перший елемент]
E --> D
8. Типові Помилки Початківців¶
Архітектурні Помилки¶
Гігантські Шаблони¶
Розміщення тисяч рядків HTML в одному файлі замість використання компонентів {% include %}.
Рішення: Виноси блоки UI, що повторюються, у директорію components/ або partials/.
Логіка у Шаблонах¶
Написання {% if note.priority == 4 and not note.is_archived and user.profile.timezone %} у шаблонах.
Рішення: Переноси у кастомний template-фільтр або сервісний шар. Тримай шаблони «дурними».
Дублювання HTML¶
Копіювання header/footer/navbar у кожен файл шаблону.
Рішення: Обов'язкове наслідування шаблонів через {% extends 'base.html' %}.
UI/UX Помилки¶
Занадто Багато Всього (Clutter/Noise)¶
Забагато елементів на одному екрані без чіткої ієрархії. Три кольори, п'ять різних розмірів шрифтів, кнопки скрізь.
Рішення: Максимум 3 рівні ієрархії в одному вью. Одна первинна дія (.btn-primary), вторинні — .btn-outline-secondary.
Слабкий Контраст¶
Сірий текст на білому фоні, «м'які» кнопки, які виглядають як текст.
Рішення: Мінімум контрасту за WCAG: 4.5:1 для звичайного тексту. Перевіряй через Colour Contrast Checker.
Неправильне Вирівнювання та Центрування¶
Розміщення елементів «на вічко», перецентрування всього — центрований лівий навігаційний сайдбар, центрована таблиця з даними.
Рішення: Bootstrap-сітка + Flexbox + вирівнювання text-start для даних, text-center тільки для заголовків/іконок.
Помилки Дизайну Форм¶
- Placeholder замість label (приховує підказку після введення першого символу)
- Кнопка «Скасувати» таким самим кольором, що й «Зберегти»
- Немає підтвердження видалення
Рішення:
{# ПОГАНО — label всередині input #}
<input placeholder="Введіть email" type="email">
{# ДОБРЕ — окремий label #}
<label for="email" class="form-label">Email</label>
<input id="email" type="email" class="form-control" placeholder="you@example.com">
Покладання Лише на Колір¶
Використання тільки кольору для позначення статусу (червоний/зелений) не працює для людей з порушенням кольорового зору.
Рішення:
{# ПОГАНО: лише колір #}
<span class="badge bg-success"></span>
{# ДОБРЕ: колір + іконка + текст #}
<span class="badge bg-success"><i class="bi bi-check-circle me-1"></i>Активний</span>
Відсутність Порожніх Станів¶
Показ порожньої таблиці або сторінки, коли даних немає.
Рішення: Завжди рендеруй компонент empty_state.html з корисним CTA.
9. Організація Великих Django-проєктів¶
Для підтримки масштабованості у production Django-застосунках:
my_project/
├── templates/ ← Глобальні компонування (base.html, layouts/)
│ ├── base.html
│ ├── layouts/
│ │ ├── dashboard.html
│ │ └── auth.html
│ └── components/ ← Елементи UI для повторного використання
│ ├── pagination.html
│ ├── empty_state.html
│ └── confirm_modal.html
│
├── my_app/
│ ├── templates/my_app/ ← Специфічні для застосунку шаблони сторінок
│ │ ├── note_list.html ← extends layouts/dashboard.html
│ │ └── note_form.html ← {% crispy form %}
│ ├── static/my_app/
│ │ ├── css/app.css ← Кастомні перевизначення (мінімум!)
│ │ └── js/app.js
│ ├── models.py
│ ├── services.py ← Бізнес-логіка (INSERT/UPDATE/DELETE)
│ ├── selectors.py ← Запити на читання (SELECT)
│ ├── views.py ← Лише HTTP-шар
│ └── forms.py ← FormHelper + Layout (crispy)
│
└── static/ ← Вивід collectstatic (production)
Правило: Уникай написання кастомного CSS для компонування, якщо грід-система (Bootstrap) вже обробляє це. Кастомний CSS має перевизначати лише брендинг (кольори, шрифти), а не компонування.
graph TD
subgraph Відповідальність Шаблонів
A[base.html] -->|extends| B[layouts/dashboard.html]
B -->|extends| C[app/page.html]
C -->|includes| D[components/pagination.html]
C -->|includes| E[components/empty_state.html]
end
subgraph Відповідальність Python
F[views.py] -->|делегує до| G[selectors.py]
F -->|делегує до| H[services.py]
F -->|передає форму до| I[forms.py FormHelper]
I -->|рендерить через| J["{% crispy form %}"]
end
10. Tailwind CSS проти Bootstrap у Django¶
Bootstrap у Django¶
Переваги:
- Готові компоненти «з коробки» (картки, модальні вікна, navbar)
- django-crispy-forms + crispy-bootstrap5 — відмінна інтеграція
- Менша крива навчання
- Просто підключити через CDN
Недоліки: - «Bootstrap-вигляд» — сайти схожі між собою без кастомізації - Більший CSS-файл (навіть із purge) - Менше гнучкості для унікальних дизайнів
Tailwind CSS у Django¶
Переваги: - Унікальний дизайн — немає «tailwind-вигляду» - Атомарні CSS-класи — менший фінальний файл (після purge) - Повний контроль над стилями без написання кастомного CSS
Недоліки:
- Потребує django-tailwind + Node.js для збірки
- crispy-tailwind — менш зрілий, ніж crispy-bootstrap5
- Вища крива навчання
- Немає готових компонентів (потрібен Flowbite, Headless UI тощо)
Інтеграція Tailwind з Django¶
# settings.py
INSTALLED_APPS = [
...
'tailwind',
'theme', # генерується django-tailwind
]
TAILWIND_APP_NAME = 'theme'
NPM_BIN_PATH = '/usr/local/bin/npm'
# Запуск у розробці:
# python manage.py tailwind start
Коли обирати що¶
| Ситуація | Рекомендація |
|---|---|
| Навчальний проєкт / прототип | Bootstrap (CDN, без збірки) |
| SaaS з унікальним брендингом | Tailwind |
| Адмін-панель / бекофіс | Bootstrap + django-unfold |
| Публічний сайт з дизайном від дизайнера | Tailwind |
| Команда знає Bootstrap добре | Bootstrap |
11. Статичні Файли у Django¶
Налаштування settings.py¶
# URL для доступу до статичних файлів у розробці
STATIC_URL = '/static/'
# Директорії зі статичними файлами ПОЗА застосунками (project-level)
STATICFILES_DIRS = [
BASE_DIR / 'static', # project/static/css/global.css
]
# Директорія для production (collectstatic)
STATIC_ROOT = BASE_DIR / 'staticfiles'
Структура Директорій¶
my_project/
├── static/ ← project-level (STATICFILES_DIRS)
│ ├── css/
│ │ └── global.css
│ └── js/
│ └── global.js
│
└── my_app/
└── static/
└── my_app/ ← namespace (важливо!)
├── css/
│ └── app.css
└── js/
└── app.js
Простір імен: Завжди кладіть файли у підпапку з назвою застосунку (static/my_app/), щоб уникнути конфліктів між застосунками при collectstatic.
Використання у Шаблонах¶
{% load static %}
{# Завантаження CSS #}
<link rel="stylesheet" href="{% static 'my_app/css/app.css' %}">
{# Завантаження JS #}
<script src="{% static 'my_app/js/app.js' %}"></script>
{# Зображення #}
<img src="{% static 'my_app/images/logo.png' %}" alt="Логотип">
Команди для Production¶
# Збирає всі статичні файли у STATIC_ROOT
python manage.py collectstatic
# Перевірка конфігурації
python manage.py findstatic css/global.css
Обслуговування у Production¶
Django не обслуговує статичні файли у production (DEBUG=False). Використовуй Nginx, WhiteNoise або CDN:
# WhiteNoise (найпростіший варіант для Heroku/Railway)
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware',
...
]
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
12. Інтеграція React з Django¶
Підхід 1: Вбудований Віджет (Embedded Widget)¶
Одна або кілька сторінок Django рендерять HTML де React монтується у конкретний <div>.
Решта застосунку — звичайні Django-шаблони.
{# Django шаблон #}
{% extends 'base.html' %}
{% block content %}
<!-- React монтується тут -->
<div id="react-root"
data-notes="{{ notes_json|escapejs }}"
data-user="{{ user.pk }}">
</div>
{% endblock %}
{% block extra_js %}
<script src="{% static 'notes_app/js/notes_widget.bundle.js' %}"></script>
{% endblock %}
Коли використовувати: Один складний компонент (наприклад, інтерактивна карта, редактор тексту), решта сайту — SSR Django.
Підхід 2: SPA + API (Повне Розділення)¶
Django надає тільки REST API (DRF або API Views), React — окремий застосунок на Vite/CRA.
backend/ ← Django REST API (порт 8000)
├── api/
│ ├── views.py ← APIView або ViewSet
│ └── serializers.py
└── settings.py ← CORS_ALLOWED_ORIGINS = ['http://localhost:5173']
frontend/ ← React + Vite (порт 5173)
├── src/
│ ├── api/ ← axios/fetch клієнти
│ └── components/
└── vite.config.js
Налаштування CORS для Django:
# pip install django-cors-headers
INSTALLED_APPS = [..., 'corsheaders']
MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware', ...]
CORS_ALLOWED_ORIGINS = ['http://localhost:5173', 'https://my-app.com']
Порівняння Підходів¶
| Критерій | Вбудований Віджет | SPA + API |
|---|---|---|
| Складність налаштування | Низька | Висока |
| SEO | Django SSR (відмінно) | Потребує SSR/SSG |
| Автентифікація Django | Вбудована (cookies/sessions) | Потрібен JWT або token |
| Повторне використання API | Обмежено | Так (мобільний, партнери) |
| Час до MVP | Швидко | Повільніше |
| Коли обирати | Один складний компонент | Повноцінний SPA |
13. Детальна Архітектура Django-шаблонів¶
Концепція SSR та Роль Шаблону¶
Django-шаблони — це потужна система Server-Side Rendering (SSR), яка суворо розділяє бізнес-логіку від представлення. У правильній бекенд-архітектурі:
- View виступає контролером: отримує дані з ORM та готує їх
- Template Engine має єдине завдання: взяти дані (контекст) та вставити їх у HTML
Django навмисно обмежує Django Template Language (DTL), щоб запобігти виконанню довільного Python-коду у шаблонах. Це архітектурне обмеження змушує тримати складну бізнес-логіку, запити до БД та мутації — виключно у View або Model.
Конвеєр Рендерингу Шаблону¶
graph TD
A[Запит Браузера] -->|URL Роутер| B[Django View]
B -->|Query| C[(База Даних)]
C -->|Model Instances| B
B -->|Context Dictionary| D[Template Engine]
D -->|Компіляція та Рендеринг| E[Скомпільований HTML-рядок]
E -->|HTTP Response| A
Кроки конвеєра:
- Request — браузер ініціює HTTP-запит, маршрутизований до Django View
- View Logic — View обробляє запит, виконує запити до БД і будує словник
context - Template Compilation — Template Engine парсить HTML-файл і компілює його у AST (дерево вузлів) у пам'яті сервера
- Context Interpolation — рушій проходить AST, замінює змінні шаблону та виконує теги
- Response Generation — рушій об'єднує результати у фінальний HTML-рядок і повертає
HttpResponse
Наслідування Шаблонів¶
Наслідування — архітектурна основа DRY UI-систем у Django. Замість копіювання <head>, навігації та футера в кожен файл — створюється базовий шаблон-«скелет» (base.html) з {% block %} тегами. Дочірні шаблони успадковують весь скелет та перевизначають лише потрібні блоки.
graph TD
A["base.html<br>HTML-скелет, Navbar, Footer, порожні Blocks"]
B["base_dashboard.html<br>Extends base.html, додає Sidebar"]
C["base_public.html<br>Extends base.html, додає Hero-секцію"]
D["analytics.html<br>Extends base_dashboard.html, Charts"]
E["settings.html<br>Extends base_dashboard.html, Forms"]
F["home.html<br>Extends base_public.html"]
B -->|"{% extends 'base.html' %}"| A
C -->|"{% extends 'base.html' %}"| A
D -->|"{% extends 'base_dashboard.html' %}"| B
E -->|"{% extends 'base_dashboard.html' %}"| B
F -->|"{% extends 'base_public.html' %}"| C
Композиція Шаблонів ({% include %})¶
Наслідування будує сторінки зверху-вниз, композиція — знизу-вгору. Складний UI розбивається на ізольовані мікрошаблони (картки, пагінація, форми), які підключаються через {% include %}.
graph LR
A[article_list.html] -->|"{% include 'components/card.html' %}"| B[card.html]
A -->|"{% include 'components/pagination.html' %}"| C[pagination.html]
A -->|"{% include 'components/navbar.html' %}"| D[navbar.html]
Розширені DTL-Теги¶
| Тег | Призначення |
|---|---|
{% extends %} / {% block %} |
Основна пара для дерев наслідування |
{% include %} |
Вставка підшаблону |
{% with %} |
Кешування складної змінної або передача ізольованих аргументів у компонент |
{% url %} |
Розв'язання іменованих URL-маршрутів у абсолютні шляхи |
{% csrf_token %} |
Вставка прихованого input з токеном безпеки від CSRF |
{% load %} |
Завантаження бібліотек тегів/фільтрів (наприклад, static, crispy_forms_tags) |
Фільтри Шаблонів¶
Фільтри трансформують дані контексту безпосередньо перед рендерингом у HTML, використовуючи синтаксис |:
| Фільтр | Приклад | Результат |
|---|---|---|
default |
{{ value\|default:"Не вказано" }} |
Fallback, якщо значення False |
length |
{{ list\|length }} |
Розмір списку або рядка |
truncatechars |
{{ text\|truncatechars:50 }} |
Обрізає рядок до N символів |
date |
{{ dt\|date:"d.m.Y" }} |
Форматує datetime |
safe |
{{ html\|safe }} |
⚠️ Вимикає HTML-екранування (тільки для перевіреного HTML!) |
lower / upper |
{{ name\|lower }} |
Регістр рядка |
Архітектурні Помилки у Шаблонах¶
| Помилка | Наслідок | Рішення |
|---|---|---|
| Бізнес-логіка у шаблонах (фільтрація QuerySet, запити до БД) | Порушення MVT, неможливість тестування | Вся підготовка даних — у View або selectors.py |
| Копіювання HTML (navbar у кожному файлі) | Зміна дизайну = правка десятків файлів | {% extends 'base.html' %} |
| Монолітні шаблони (2000+ рядків HTML) | Неможливість підтримки | {% include %} компоненти |
Зловживання \|safe на недовіреному введенні |
XSS-уразливості | Ніколи не використовуй \|safe для даних від користувача |
14. Детальна Архітектура Crispy Forms¶
Основна Концепція¶
Стандартні Django Forms відмінно справляються з валідацією даних та безпекою, але навмисно залишають HTML-компонування неструктурованим. Методи as_p(), as_table() генерують сирий HTML без Bootstrap-класів.
Django Crispy Forms вирішує це, виступаючи потужним шаром UI-абстракції. Він перехоплює стандартний рендеринг Django та програматично вставляє специфічні для фреймворку стилі прямо з Python-коду, тримаючи архітектуру UI DRY та різко зменшуючи boilerplate.
Конвеєр Рендерингу Форми¶
graph TD
A[Django Model] -->|Meta introspection| B[ModelForm]
B -->|Field instantiation| C[Поля Форми]
C -->|Type mapping| D[Widgets]
D -->|Перехоплення Crispy| E[Crispy FormHelper]
E -->|Інжекція Template Pack| F[Стилізований HTML Output]
F --> G[Браузер]
Без Crispy Forms конвеєр зупиняється на Widgets — виходить сирий HTML без Bootstrap-класів.
З Crispy Forms — FormHelper перехоплює рендеринг та через CRISPY_TEMPLATE_PACK автоматично додає всі потрібні класи.
Архітектура Crispy Forms¶
graph TD
A[Django Form] --> B[FormHelper Instance]
B --> C["form_method = 'POST'"]
B --> D[Layout Object]
D --> E[Row / Column]
D --> F[Fieldset / Div]
B --> G[Submit Button]
B --> H["Template: {% crispy form %}"]
H --> I[Повністю Стилізована Bootstrap Form]
Компоненти FormHelper¶
FormHelper — оркестратор, прикріплений до форми, що визначає:
- Атрибути тегу <form> (method, id, class, action)
- HTTP-метод (GET/POST)
- Загальну структуру Layout
FormHelper НЕ впливає на:
- Валідацію (is_valid() працює ідентично)
- cleaned_data (не змінюється)
- Бізнес-логіку
Компоненти Layout¶
| Компонент | Рендеринг у HTML | Призначення |
|---|---|---|
Fieldset('назва', ...) |
<fieldset><legend>назва</legend> |
Групування пов'язаних полів |
Row(...) |
<div class="row"> |
Bootstrap-рядок сітки |
Column('поле', css_class='col-md-6') |
<div class="col-md-6"> |
Bootstrap-колонка |
Field('поле', placeholder='...') |
<input class="form-control" ...> |
Поле з HTML-атрибутами |
Div('поле', css_class='custom') |
<div class="custom"> |
Довільний контейнер |
Submit('submit', 'Зберегти') |
<button type="submit" class="btn"> |
Кнопка відправки |
HTML('<hr>') |
Довільний HTML-рядок | Вставка будь-якого HTML |
ButtonHolder(...) |
<div class="form-group"> |
Групування кнопок |
Інтеграція з Bootstrap 5¶
Встановивши CRISPY_TEMPLATE_PACK = 'bootstrap5', Crispy Forms автоматично:
- Обгортає inputs у Bootstrap-сітку
- Вставляє обов'язковий клас .form-control у текстові поля
- Динамічно застосовує .is-invalid разом з Bootstrap-повідомленнями про помилки валідації
Конвеєр Валідації¶
graph TD
A[Браузер] -->|POST-запит| B[Django Form з request.POST]
B --> C{is_valid?}
C -->|Так| D[form.cleaned_data → Save]
C -->|Ні| E[form.errors генеруються]
E --> F[Crispy Template Pack]
F -->|Інжектує .is-invalid CSS| G[Повторний рендеринг з Bootstrap-станами валідації]
G --> A
Розширена Система Layout¶
# Приклад складного Layout — чистий Python, ніякого HTML у шаблоні!
self.helper.layout = Layout(
Fieldset(
'Основна інформація', # → <legend>
Field('title', autofocus=True), # → <input class="form-control" autofocus>
Row(
Column('priority', css_class='col-md-4'), # → <div class="col-md-4">
Column('notebook', css_class='col-md-8'), # → <div class="col-md-8">
),
),
Fieldset(
'Зміст',
Field('content', rows=8),
),
HTML('<hr class="my-4">'),
Submit('submit', 'Зберегти', css_class='btn btn-primary me-2'),
HTML('<a href="javascript:history.back()" class="btn btn-outline-secondary">Скасувати</a>'),
)
Поширені Хибні Уявлення¶
| Хибне уявлення | Правда |
|---|---|
| Crispy Forms — це валідація | Ні. Crispy впливає лише на представлення. Валідація — виключно Django |
| Crispy замінює Django Forms | Ні. Це обгортка-покращення. Ти все ще визначаєш поля та Meta як завжди |
| Crispy змінює дані | Ні. Лише трансформує HTML-вивід: <form> теги, CSRF-токени, CSS-класи |
Порівняння: Before vs After¶
BEFORE — ручний Bootstrap (notes_chat_app):
class NoteFormManual(forms.ModelForm):
class Meta:
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '...'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 8}),
'priority': forms.Select(attrs={'class': 'form-select'}),
# ... повторити для КОЖНОГО поля!
}
# Шаблон: 60+ рядків Bootstrap HTML
AFTER — Crispy Forms (crispy_notes_chat_app):
class NoteForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.layout = Layout(
Row(Column('title'), Column('priority')),
'content',
Submit('submit', 'Зберегти'),
)
# Шаблон: {% crispy form %} — 1 рядок!
Пов'язані Файли¶
| Файл | Що показує |
|---|---|
| BOOTSTRAP_5.md | Грід-система, breakpoints, утилітарні класи |
| DJANGO_TEMPLATES_BOOTSTRAP.md | Наслідування шаблонів, DTL-синтаксис, SSR |
| ADVANCED_TEMPLATES.md §3 | crispy-forms FormHelper + Layout — теорія |
| ADVANCED_TEMPLATES.md §5 | Архітектура SaaS-Дашборду — 3-рівнева ієрархія |
| CRISPY_FORMS.md | Короткий довідник по django-crispy-forms |
| crispy_notes_chat_app/ | Практична демонстрація всіх концепцій вище |
Навчальний шлях: Прочитай цей файл → вивчи
ADVANCED_TEMPLATES.md §3 + §5→ запустиcrispy_notes_chat_app→ порівняйnote_form_raw.html,note_form_manual.html,note_form.html