Перейти к основному содержимому

Справочник по Django


Назначение

Справочник-шпаргалка по Django — типы, синтаксис, стандартная библиотека, типовые паттерны. Не заменяет пошаговое обучение. Маршрут: первая программа → этот справочник → практикумDRF. Обзор архитектуры — Django.


Краткое пояснение

Компоненты и ключевые особенности фреймворка.


Быстрый старт

python manage.py check --deploy

Справочные таблицы

Содержание справочника


1. Структура проекта Django

Проект Django состоит из следующих основных компонентов:

  • manage.py — скрипт командной строки для взаимодействия с проектом (запуск сервера, миграции, создание суперпользователя и т.д.).
  • settings.py — центральный файл конфигурации проекта.
  • urls.py — корневой файл маршрутизации запросов.
  • wsgi.py — точка входа для WSGI-совместимых веб-серверов.
  • asgi.py — точка входа для ASGI-совместимых серверов (для асинхронных приложений).
  • apps/ — директории приложений, каждая из которых содержит:
    • models.py — определения моделей данных.
    • views.py — логика обработки HTTP-запросов.
    • urls.py — маршруты, специфичные для приложения.
    • admin.py — регистрация моделей в админке.
    • forms.py — определения пользовательских форм.
    • tests.py или tests/ — модульные и интеграционные тесты.
    • migrations/ — автоматически генерируемые файлы миграций базы данных.
    • static/ — статические файлы (CSS, JS, изображения).
    • templates/ — HTML-шаблоны.

2. Настройки (settings.py)

Файл settings.py содержит параметры, управляющие поведением проекта. Все настройки являются переменными верхнего регистра.


Основные настройки

  • BASE_DIR — путь к корню проекта (Path(__file__).resolve().parent.parent).
  • SECRET_KEY — секретный ключ, используемый для криптографических подписей. Обязателен для работы.
  • DEBUG — режим отладки. При значении True отображаются подробные ошибки. В продакшене должен быть False.
  • ALLOWED_HOSTS — список доменов или IP-адресов, которые могут обслуживать приложение. Пример: ['example.com', '192.168.1.1'].
  • INSTALLED_APPS — список установленных приложений. Может включать:
    • встроенные приложения Django ('django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles');
    • сторонние приложения;
    • собственные приложения проекта.
  • MIDDLEWARE — список промежуточных слоёв, обрабатывающих запросы и ответы. Порядок важен. Стандартные middleware:
    • 'django.middleware.security.SecurityMiddleware'
    • 'django.contrib.sessions.middleware.SessionMiddleware'
    • 'django.middleware.common.CommonMiddleware'
    • 'django.middleware.csrf.CsrfViewMiddleware'
    • 'django.contrib.auth.middleware.AuthenticationMiddleware'
    • 'django.contrib.messages.middleware.MessageMiddleware'
    • 'django.middleware.clickjacking.XFrameOptionsMiddleware'

База данных

  • DATABASES — словарь конфигураций баз данных. По умолчанию используется SQLite:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}

Другие поддерживаемые движки:

  • 'django.db.backends.postgresql'
  • 'django.db.backends.mysql'
  • 'django.db.backends.oracle'

Дополнительные параметры:

  • USER — имя пользователя БД.
  • PASSWORD — пароль.
  • HOST — хост (например, 'localhost').
  • PORT — порт (например, '5432' для PostgreSQL).
  • OPTIONS — дополнительные параметры подключения (например, SSL-настройки).
  • CONN_MAX_AGE — время жизни соединения в секундах (для пула соединений).

Несколько баз в одном проекте — ключ 'default' плюс дополнительные имена:

DATABASES = {
'default': {'ENGINE': 'django.db.backends.postgresql', ...},
'archive': {'ENGINE': 'django.db.backends.postgresql', ...},
}

Маршрутизация запросов к нужной БД — DATABASE_ROUTERS (список классов с методами db_for_read, db_for_write, allow_relation, allow_migrate). В коде: Model.objects.using('archive').filter(...), в командах: python manage.py migrate --database=archive.


Локализация и интернационализация

  • LANGUAGE_CODE — код языка по умолчанию ('en-us', 'ru').
  • TIME_ZONE — часовой пояс ('UTC', 'Europe/Moscow').
  • USE_I18N — активация интернационализации (True/False).
  • USE_TZ — использование временных зон (True/False).

Статические файлы и медиа

  • STATIC_URL — URL-префикс для статических файлов ('/static/').
  • STATICFILES_DIRS — список дополнительных директорий для сбора статики:
STATICFILES_DIRS = [BASE_DIR / "static"]
  • STATIC_ROOT — директория, куда собираются все статические файлы командой collectstatic.
  • MEDIA_URL — URL-префикс для медиафайлов ('/media/').
  • MEDIA_ROOT — путь к директории, где хранятся загруженные файлы (BASE_DIR / 'media').

Безопасность

  • SECURE_HSTS_SECONDS — включение HTTP Strict Transport Security (в секундах).
  • SECURE_SSL_REDIRECT — принудительное перенаправление на HTTPS.
  • SESSION_COOKIE_SECURE — отправка cookie только по HTTPS.
  • CSRF_COOKIE_SECURE — защита CSRF-токена через HTTPS.
  • SECURE_BROWSER_XSS_FILTER — включение XSS-фильтра браузера.
  • SECURE_CONTENT_TYPE_NOSNIFF — запрет MIME-sniffing.

Аутентификация

  • AUTH_USER_MODEL — кастомная модель пользователя (по умолчанию 'auth.User').
  • LOGIN_URL — URL для перенаправления неавторизованных пользователей.
  • LOGOUT_REDIRECT_URL — URL после выхода.
  • LOGIN_REDIRECT_URL — URL после входа.

Кэширование

  • CACHES — конфигурация кэша:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}

Поддерживаемые бэкенды:

  • 'django.core.cache.backends.locmem.LocMemCache'
  • 'django.core.cache.backends.filebased.FileBasedCache'
  • 'django.core.cache.backends.memcached.PyMemcacheCache'
  • 'django.core.cache.backends.redis.RedisCache'

Почта

  • EMAIL_BACKEND — бэкенд отправки почты:
    • 'django.core.mail.backends.smtp.EmailBackend'
    • 'django.core.mail.backends.console.EmailBackend' (для разработки)
  • EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, EMAIL_USE_TLS, EMAIL_USE_SSL — параметры SMTP.

Логирование

  • LOGGING — словарь конфигурации логгера (форматы, обработчики, уровни, логгеры).

3. Модели (models.py)

Модели описывают структуру данных и взаимодействие с базой данных.


Базовые поля

Каждое поле модели — экземпляр класса Field. Основные типы:

  • CharField(max_length=...) — строка ограниченной длины.
  • TextField() — длинный текст.
  • IntegerField(), BigIntegerField(), SmallIntegerField(), PositiveIntegerField(), PositiveSmallIntegerField() — целые числа разных диапазонов.
  • FloatField(), DecimalField(max_digits=..., decimal_places=...) — числа с плавающей точкой.
  • BooleanField() — логическое значение.
  • DateField(), DateTimeField(), TimeField() — дата и время.
    • Параметры: auto_now=True (обновляется при каждом сохранении), auto_now_add=True (устанавливается при создании).
  • EmailField() — проверка email-формата.
  • URLField() — проверка URL.
  • FileField(upload_to=...) — загрузка файла.
  • ImageField(upload_to=...) — загрузка изображения (требует Pillow).
  • ForeignKey(to, on_delete=...) — связь "многие к одному".
  • OneToOneField(to, on_delete=...) — связь "один к одному".
  • ManyToManyField(to) — связь "многие ко многим".

Параметры полей

  • null=True — разрешает NULL в БД.
  • blank=True — разрешает пустое значение в формах.
  • default=value — значение по умолчанию.
  • unique=True — уникальность значения.
  • choices=[(value, label), ...] — предопределённые варианты выбора.
  • help_text="..." — подсказка в формах.
  • verbose_name="..." — человекочитаемое имя поля.

Мета-класс (Meta)

Внутри модели можно определить вложенный класс Meta:

  • db_table = "custom_name" — имя таблицы в БД.
  • ordering = ["field"] — порядок по умолчанию.
  • verbose_name = "...", verbose_name_plural = "..." — отображаемые имена.
  • unique_together = [("field1", "field2")] — составной уникальный ключ.
  • indexes = [models.Index(fields=["field"]), ...] — индексы.
  • constraints = [models.CheckConstraint(...), ...] — ограничения уровня БД.

Расширенные типы моделей

Подходclass MetaТаблица в БДЗадача
Абстрактнаяabstract = Trueнет своейобщие поля для наследников
Проксиproxy = Trueта же, что у родителядругой Python-API без дублирования данных
Multi-table inheritanceнаследование без abstractотдельная на каждый уровеньрасширение сущности новыми полями

Кастомный менеджер:

class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_published=True)

class Article(models.Model):
objects = models.Manager()
published = PublishedManager()

Транзакции: from django.db import transaction и with transaction.atomic(): — все операции внутри блока фиксируются или откатываются вместе.


Методы модели

  • str(self) — строковое представление объекта.
  • get_absolute_url() — канонический URL объекта.
  • save() — переопределение логики сохранения.
  • delete() — переопределение удаления.

4. Представления (views.py)

Представления — это функции или классы, которые принимают HTTP-запрос и возвращают HTTP-ответ. Они реализуют логику приложения.


Типы представлений

Функциональные представления (Function-Based Views, FBV)

Пример:

from django.http import HttpResponse
from django.shortcuts import render

def home(request):
return render(request, 'home.html', {'title': 'Главная'})

Доступные утилиты из django.shortcuts:

  • render(request, template_name, context) — рендерит шаблон и возвращает HttpResponse.
  • redirect(to, *args, **kwargs) — перенаправляет на другой URL.
  • get_object_or_404(model, **kwargs) — возвращает объект или вызывает 404.
  • get_list_or_404(queryset) — возвращает список или вызывает 404.

Классовые представления (Class-Based Views, CBV)

Стандартные CBV из django.views.generic:

  • TemplateView — рендерит шаблон.
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "about.html"
  • ListView — отображает список объектов.

    • model = MyModel
    • template_name = "list.html"
    • context_object_name = "items" — имя переменной в шаблоне.
    • paginate_by = 10 — пагинация.
  • DetailView — отображает один объект.

    • model = MyModel
    • template_name = "detail.html"
    • По умолчанию ожидает параметр pk или slug в URL.
  • CreateView, UpdateView, DeleteView — операции CRUD.

    • model, fields, form_class, success_url — основные параметры.
    • get_success_url() — метод для динамического определения URL после успешного действия.
  • FormView — обработка произвольной формы без привязки к модели.

Подключение CBV в urls.py — через as_view():

from django.urls import path
from .views import ArticleListView, ArticleCreateView

urlpatterns = [
path('', ArticleListView.as_view(), name='article_list'),
path('add/', ArticleCreateView.as_view(), name='article_add'),
]

Примеси (mixins) и состав CBV

Generic CBV собираются из примесей. Частые блоки:

ПримесьНазначение
ContextMixinформирует словарь контекста шаблона (get_context_data)
TemplateResponseMixintemplate_name, рендеринг
SingleObjectMixinзагрузка одной записи по pk или slug
MultipleObjectMixinqueryset списка, пагинация
FormMixinсоздание и валидация формы
ModelFormMixinModelForm по полям модели
DeletionMixinудаление с подтверждением
LoginRequiredMixinдоступ только авторизованным
PermissionRequiredMixinпроверка permission_required

Хронологические списки — ArchiveIndexView, YearArchiveView, MonthArchiveView, DayArchiveView, TodayArchiveView — фильтрация по дате из URL.


Пагинатор

Класс django.core.paginator.Paginator делит queryset на страницы. В CBV достаточно paginate_by = 10 в ListView; в FBV пагинатор подключают вручную.

from django.core.paginator import Paginator
from django.shortcuts import render

def article_list(request):
queryset = Article.objects.order_by('-created_at')
paginator = Paginator(queryset, per_page=10)
page = paginator.get_page(request.GET.get('page'))
return render(request, 'articles/list.html', {'page': page})

В шаблоне: цикл {% for article in page %}, навигация {% if page.has_previous %}, {{ page.number }} из {{ page.paginator.num_pages }}.

Метод / атрибутСмысл
get_page(n)страница n; при ошибке — первая или последняя
page.object_listзаписи текущей страницы
page.has_next / has_previousесть ли соседние страницы

Асинхронные представления

Начиная с Django 3.1, поддерживаются асинхронные представления:

async def async_view(request):
data = await fetch_data_from_api()
return render(request, 'async.html', {'data': data})

Асинхронные CBV также доступны через AsyncView и производные.


5. Маршрутизация (URLconf)

Маршрутизация связывает URL-адреса с представлениями.


Основные элементы

  • urlpatterns — список маршрутов в urls.py.

  • path(route, view, kwargs=None, name=None) — современный способ определения маршрута.

    • route — строка пути (например, 'articles/<int:id>/').
    • view — функция или результат as_view().
    • name — имя маршрута для обратного разрешения (reverse() или {% url %}).
  • re_path(route, view, kwargs=None, name=None) — маршрут с регулярным выражением (устаревший, но иногда необходим).


Параметры маршрутов

  • <int:id> — целое число.
  • <str:slug> — строка (не содержит /).
  • <slug:slug> — slug (латиница, цифры, дефис, подчёркивание).
  • <uuid:token> — UUID.
  • <path:url> — любой путь, включая /.

Включение приложений

Корневой urls.py подключает маршруты приложений:

from django.urls import include, path

urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')),
]

Внутри blog/urls.py:

from django.urls import path
from . import views

urlpatterns = [
path('', views.post_list, name='post_list'),
path('<int:pk>/', views.post_detail, name='post_detail'),
]

Обратное разрешение URL

  • В Python: reverse('post_detail', args=[123])
  • В шаблонах: {% url 'post_detail' pk=123 %}

6. Шаблоны (templates)

Шаблоны — это HTML-файлы с встроенными тегами и переменными Django.


Структура шаблонов

  • Базовый шаблон (base.html) содержит общую структуру:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Сайт{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
  • Дочерние шаблоны наследуют базовый:
{% extends "base.html" %}
{% block title %}Главная{% endblock %}
{% block content %}
<h1>Добро пожаловать!</h1>
{% endblock %}

Переменные

  • {{ variable }} — вывод значения.
  • {{ object.attribute }} — доступ к атрибуту.
  • {{ dict.key }} — доступ к ключу словаря.
  • {{ list.0 }} — первый элемент списка.

Фильтры

Изменяют значение переменной:

  • {{ name|upper }}
  • {{ date|date:"d.m.Y" }}
  • {{ text|truncatewords:15 }}
  • {{ list|length }}
  • {{ value|default:"Нет данных" }}

Теги

  • {% for item in items %}...{% endfor %}
  • {% if condition %}...{% elif %}...{% else %}...{% endif %}
  • {% include "partial.html" %}
  • {% csrf_token %} — обязательный токен для форм.
  • {% load static %} — загрузка статических файлов.
  • {% url 'name' arg %} — генерация URL.

Контекст шаблона

Передаётся как словарь из представления. Автоматически добавляются:

  • user — текущий пользователь.
  • request — объект запроса (если включён RequestContext).
  • messages — сообщения Django.

7. Формы (forms.py)

Формы обеспечивают валидацию и рендеринг пользовательского ввода.


Типы форм

Обычные формы (Form)
from django import forms

class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)

Модельные формы (ModelForm)

Автоматически создаются на основе модели:

class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'content', 'author']
# или fields = '__all__'
# exclude = ['created_at']

Поля формы

Соответствуют полям модели, но с префиксом forms.:

  • CharField, EmailField, URLField, IntegerField, BooleanField, DateField, DateTimeField, ChoiceField, FileField, ImageField и др.

Виджеты (widgets)

Определяют HTML-представление поля:

  • TextInput, Textarea, EmailInput, NumberInput, DateInput, CheckboxInput, Select, FileInput, ClearableFileInput.

Пример:

message = forms.CharField(widget=forms.Textarea(attrs={'rows': 5, 'class': 'form-control'}))

Валидация

  • clean_<field>() — валидация конкретного поля.
  • clean() — валидация всей формы.
  • raise forms.ValidationError("Ошибка") — генерация ошибки.

Обработка в представлении

def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
# обработка данных: form.cleaned_data
return redirect('success')
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})

Рендеринг в шаблоне

<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Отправить</button>
</form>

Альтернативы:

  • {{ form.as_table }}
  • {{ form.as_ul }}
  • Ручной рендеринг: {{ form.name.label_tag }} {{ form.name }}

Наборы форм (formsets)

Несколько однотипных форм на одной странице (например, несколько строк заказа). Базовый класс — BaseFormSet; для моделей — BaseModelFormSet.

from django.forms import modelformset_factory
from .models import OrderLine

OrderLineFormSet = modelformset_factory(
OrderLine,
fields=['product', 'quantity'],
extra=3, # пустых форм «с запасом»
can_delete=True,
)

В представлении:

def edit_order(request, order_id):
queryset = OrderLine.objects.filter(order_id=order_id)
if request.method == 'POST':
formset = OrderLineFormSet(request.POST, queryset=queryset)
if formset.is_valid():
formset.save()
return redirect('order_detail', order_id)
else:
formset = OrderLineFormSet(queryset=queryset)
return render(request, 'order_lines.html', {'formset': formset})

В шаблоне: {{ formset.management_form }}, цикл {% for form in formset %}.

Inline formsets — формы дочерних записей рядом с родителем (ForeignKey):

from django.forms import inlineformset_factory

LineInlineFormSet = inlineformset_factory(
Order, OrderLine, fields=['product', 'quantity'], extra=1,
)

В админке те же идеи даёт class OrderLineInline(admin.TabularInline): model = OrderLine.

Валидация всего набора — метод clean() у класса formset (не у отдельной формы).


8. Административная панель (admin.py)

Админка — встроенная система управления данными, автоматически генерируемая на основе моделей.


Регистрация модели

from django.contrib import admin
from .models import Article

admin.site.register(Article)

Настройка отображения

Создание кастомного класса ModelAdmin:

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'created_at')
list_filter = ('created_at', 'author')
search_fields = ('title', 'content')
prepopulated_fields = {'slug': ('title',)}
date_hierarchy = 'created_at'
ordering = ('-created_at',)
fields = ('title', 'slug', 'content', 'author')
readonly_fields = ('created_at',)
autocomplete_fields = ('author',)

Дополнительные возможности

  • list_editable — редактирование полей прямо в списке.
  • actions — массовые действия (например, публикация выбранных статей).
  • inlines — встраивание связанных объектов (например, комментариев под статьёй).
  • get_queryset() — ограничение видимых записей (например, только свои).
  • has_add_permission(), has_change_permission(), has_delete_permission() — управление правами.

Пример inline и действия в списке:

class CommentInline(admin.TabularInline):
model = Comment
extra = 1

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
inlines = [CommentInline]
list_display = ('title', 'is_published')
actions = ['make_published']

@admin.action(description='Опубликовать выбранные')
def make_published(self, request, queryset):
queryset.update(is_published=True)

Расширенная настройка ModelAdmin

fieldsets — группы полей на форме правки:

fieldsets = (
(None, {'fields': ('title', 'rubric', 'author')}),
('Текст', {'fields': ('content', 'price')}),
('Статус', {'fields': ('published',), 'classes': ('collapse',)}),
)

Метод в list_display — вычисляемый столбец без поля в модели:

@admin.display(description='Цена, ₽', ordering='price')
def price_display(self, obj):
return f'{obj.price:.2f}' if obj.price is not None else '—'

readonly_fields — поля только для чтения (created_at, slug после создания).

autocomplete_fields — поиск по FK в больших таблицах (нужен search_fields у связанной модели в её ModelAdmin).

save_model — логика при сохранении из админки:

def save_model(self, request, obj, form, change):
if not change:
obj.author = request.user
super().save_model(request, obj, form, change)

Кастомный AdminSite — отдельная админка для подсистемы:

from django.contrib.admin import AdminSite

class StaffAdminSite(AdminSite):
site_header = 'Управление каталогом'
index_title = 'Модерация'

staff_admin = StaffAdminSite(name='staff_admin')
staff_admin.register(Listing, ListingAdmin)

В корневом urls.py: path('staff/', staff_admin.urls).


9. Миграции (migrations)

Миграции — это способ синхронизации изменений в моделях с базой данных.


Основные команды

  • python manage.py makemigrations — создаёт новые миграции на основе изменений в models.py.
python manage.py makemigrations
  • python manage.py migrate — применяет миграции к БД.
python manage.py migrate
  • python manage.py showmigrations — показывает статус всех миграций.
python manage.py showmigrations
  • python manage.py sqlmigrate app_name 0001 — отображает SQL-код миграции.
python manage.py sqlmigrate app_name 0001
  • python manage.py migrate --fake — помечает миграцию как применённую без выполнения SQL.
python manage.py migrate --fake
  • python manage.py migrate --fake-initial — обход для существующих таблиц.
python manage.py migrate --fake-initial

Типы миграций

  • Initial — первая миграция приложения.
  • Данные migrations — миграции с пользовательским кодом (например, заполнение данных).
  • Squashed migrations — объединение нескольких миграций в одну для ускорения.
python manage.py squashmigrations myapp 0001 0008

Откат к состоянию приложения: python manage.py migrate myapp 0003 (номер — целевая миграция).


Ручное создание миграции

from django.db import migrations

def populate_data(apps, schema_editor):
Article = apps.get_model('blog', 'Article')
Article.objects.create(title="Пример", content="...")

class Migration(migrations.Migration):
dependencies = [('blog', '0001_initial')]
operations = [migrations.RunPython(populate_data)]

10. Сигналы (signals)

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


Встроенные сигналы

  • pre_save, post_save — до и после сохранения.
  • pre_delete, post_delete — до и после удаления.
  • m2m_changed — изменение связи "многие ко многим".
  • request_started, request_finished — начало и завершение запроса.

Регистрация обработчика

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Article

@receiver(post_save, sender=Article)
def send_notification(sender, instance, created, **kwargs):
if created:
# отправить уведомление
pass

Или вручную:

post_save.connect(send_notification, sender=Article)

Рекомендации

  • Избегайте сложной логики в сигналах — они усложняют отладку.
  • Используйте сигналы для кэширования, логирования, уведомлений.

11. Middleware

Middleware — это компоненты, обрабатывающие запросы до представления и ответы после него.


Стандартные middleware

Уже перечислены в разделе "Настройки", но ключевые функции:

  • SecurityMiddleware — защита от кликджекинга, XSS, HSTS.
  • SessionMiddleware — управление сессиями.
  • CsrfViewMiddleware — защита от CSRF-атак.
  • AuthenticationMiddleware — привязка пользователя к запросу.

Создание собственного middleware

class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
# Код до вызова представления
response = self.get_response(request)
# Код после вызова представления
return response

Регистрация в MIDDLEWARE:

MIDDLEWARE = [
...
'myapp.middleware.SimpleMiddleware',
]

Методы middleware

  • process_request(request) — обработка запроса.
  • process_view(request, view_func, view_args, view_kwargs) — перед вызовом представления.
  • process_exception(request, exception) — при возникновении исключения.
  • process_response(request, response) — обработка ответа.

Сообщения для пользователя (messages)

django.contrib.messages хранит одноразовые уведомления в сессии (успех, ошибка, предупреждение). Требуют MessageMiddleware и django.contrib.messages в INSTALLED_APPS.

from django.contrib import messages

def publish_article(request, pk):
article = get_object_or_404(Article, pk=pk)
article.is_published = True
article.save()
messages.success(request, 'Статья опубликована.')
return redirect('article_detail', pk=pk)

В шаблоне:

{% if messages %}
{% for message in messages %}
<p class="{{ message.tags }}">{{ message }}</p>
{% endfor %}
{% endif %}

Сессия — данные на сервере (или в signed cookie), ключ — sessionid в cookie браузера. В view:

request.session['cart_id'] = cart.id
request.session.get('theme', 'light')
del request.session['draft']

SESSION_ENGINE — где хранить: django.contrib.sessions.backends.db (таблица), cache, cached_db, file. SESSION_COOKIE_AGE — время жизни в секундах; SESSION_COOKIE_SECURE = True в HTTPS.

Cookie напрямуюresponse.set_cookie('visited', '1', max_age=3600); чтение — request.COOKIES.get('visited'). Для чувствительных данных используют сессию, а не произвольные cookie.

Очистка устаревших сессий: python manage.py clearsessions (cron).


Обработчики контекста (context processors)

Функции, добавляющие переменные во все шаблоны (если используется RequestContext):

# catalog/context_processors.py
def rubrics(request):
from .models import Rubric
return {'nav_rubrics': Rubric.objects.all()[:20]}

В settings.pyTEMPLATES[0]['OPTIONS']['context_processors'] дописать 'catalog.context_processors.rubrics'. Удобно для меню рубрик на доске объявлений; тяжёлые запросы лучше кешировать внутри processor.


12. Тестирование

Django предоставляет мощную систему тестирования на основе unittest.


Типы тестов

  • Unit tests — проверка отдельных функций или методов.
  • Integration tests — проверка взаимодействия компонентов.
  • Functional tests — проверка сквозного поведения (часто через LiveServerTestCase).

Базовый класс**

from django.test import TestCase
from .models import Article

class ArticleTestCase(TestCase):
def setUp(self):
Article.objects.create(title="Тест", content="...")

def test_article_title(self):
article = Article.objects.get(title="Тест")
self.assertEqual(article.title, "Тест")

Клиент для тестирования HTTP

def test_home_page(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Добро пожаловать")

Фикстуры и фабрики

  • Fixtures — JSON/YAML файлы с начальными данными.
  • Factory Boy — сторонняя библиотека для генерации тестовых данных.

Запуск тестов

  • python manage.py test — запуск всех тестов.
python manage.py test
  • python manage.py test myapp.tests.ArticleTestCase — запуск конкретного класса.
python manage.py test myapp.tests.ArticleTestCase

13. Управление статикой и медиа

Статические файлы

  • Размещаются в static/ внутри приложений или в STATICFILES_DIRS.
  • В шаблонах: {% load static %} <link href="{% static 'css/style.css' %}" rel="stylesheet">
  • В продакшене: python manage.py collectstatic собирает всё в STATIC_ROOT.
python manage.py collectstatic

Медиафайлы

  • Загружаются в MEDIA_ROOT.
  • Доступны по URL MEDIA_URL.
  • В разработке требуется настройка маршрутов:
from django.conf import settings
from django.conf.urls.static import static

if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

В продакшене раздачу MEDIA_URL обычно настраивает Nginx или object storage (S3), а не Django.

Модель с загрузкой:

class Document(models.Model):
title = models.CharField(max_length=200)
file = models.FileField(upload_to='documents/%Y/%m/')
image = models.ImageField(upload_to='photos/', blank=True)

ModelForm подхватывает FileField / ImageField; в шаблоне у формы обязателен enctype="multipart/form-data".

<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
</form>

В представлении для POST передают request.FILES: form = DocumentForm(request.POST, request.FILES). Ограничение размера — DATA_UPLOAD_MAX_MEMORY_SIZE в settings.py и настройки веб-сервера.


14. Безопасность

Django включает множество встроенных механизмов защиты:

  • CSRF-токены — обязательны для POST-форм.
  • XSS-защита — автоматическое экранирование переменных в шаблонах.
  • SQL-инъекции — предотвращаются использованием ORM.
  • Clickjacking protection — заголовок X-Frame-Options.
  • Password hashing — используется PBKDF2 или Argon2.
  • Rate limiting — не встроен, но реализуется через middleware или Redis.

Рекомендуется регулярно обновлять Django и использовать django-check или bandit для аудита.


Встроенные CBV аутентификации

Модуль django.contrib.auth.views даёт готовые class-based views для входа, выхода и сброса пароля. Подключают в urls.py:

Код ITЗагрузка примера кода…

Цепочка сброса пароля: форма email → письмо со ссылкой → ввод нового пароля по токену → страница "готово". Для писем нужны EMAIL_* в settings.py (см. §21).

Защита представлений:

from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin

@login_required
def dashboard(request): ...

class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
fields = ['title', 'content']

class ReportView(PermissionRequiredMixin, TemplateView):
permission_required = 'reports.view_report'
template_name = 'report.html'

Группы и права на модели — через админку (auth.Group, Permission) или user.has_perm('app_label.codename').


15. Производительность

Оптимизация запросов

  • select_related() — жадная загрузка связей "один ко многим".
  • prefetch_related() — жадная загрузка связей "многие ко многим".
  • only(), defer() — выборка только нужных полей.
  • count(), exists() — эффективные проверки вместо len(queryset).

Кэширование

УровеньКакКогда
Страница@cache_page(60 * 15) на viewредко меняющиеся публичные страницы
Фрагмент шаблона{% cache 600 sidebar %}...{% endcache %}меню, футер
Объектcache.set('post:1', data, 300)дорогой расчёт, счётчики
QuerySetcache.get_or_set('rubric_list', lambda: list(Rubric.objects.all()), 3600)справочники

Бэкенды в CACHESLocMemCache (один процесс), RedisCache, Memcached. В продакшене для нескольких воркеров Gunicorn нужен общий бэкенд (Redis), иначе кэш "разъедется" по процессам.

Инвалидация: явный cache.delete('key') в save() модели или в сигнале post_save. @cache_page сбрасывают сменой URL или версией в ключе (@cache_page(60, key_prefix='v2')).

CACHE_MIDDLEWARE_SECONDS + UpdateCacheMiddleware / FetchFromCacheMiddleware — кэш всего ответа на уровне middleware (осторожно с персонализированными страницами).


Профилирование

  • django-debug-toolbar — инструмент для разработки.
  • Логирование медленных запросов через LOGGING.

16. Развёртывание

Подготовка к продакшену

  • Установить DEBUG = False
  • Настроить ALLOWED_HOSTS
  • Настроить статику через Nginx/Apache
  • WSGI: Gunicorn или uWSGI + Nginx
  • ASGI — Uvicorn, Daphne или Hypercorn (WebSocket, async views)
  • Настроить SSL
  • Настроить резервное копирование БД

ASGI и Uvicorn

asgi.py — точка входа для ASGI-серверов. Запуск Uvicorn из корня проекта:

pip install uvicorn
uvicorn myproject.asgi:application --host 0.0.0.0 --port 8000

Для продакшена часто ставят Nginx перед Uvicorn и несколько воркеров. Синхронный ORM в async-view по-прежнему требует осторожности; тяжёлый I/O к БД в async-цепочке лучше выносить в sync-view или использовать async-совместимый драйвер PostgreSQL.


Проверка конфигурации

python manage.py check --deploy

Среды

  • Использовать .env файлы (через python-decouple или django-environ)
  • Отдельные settings/production.py, settings/development.py

Docker

Типичный Dockerfile:

FROM python:3.11
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["gunicorn", "myproject.wsgi:application"]

17. REST API с Django REST Framework (DRF)

Django REST Framework — мощное расширение для создания API.


Установка

pip install djangorestframework

Добавить в INSTALLED_APPS:

INSTALLED_APPS = [
...
'rest_framework',
]

Сериализаторы

Преобразуют объекты Python в JSON и обратно.

from rest_framework import serializers
from .models import Article

class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'title', 'content', 'author']

Поддержка вложенных объектов:

author = UserSerializer(read_only=True)

Валидация:

def validate_title(self, value):
if "спам" in value.lower():
raise serializers.ValidationError("Заголовок содержит запрещённое слово")
return value

Представления API

Функциональные представления с декораторами
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(['GET'])
def article_list(request):
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)

Классовые представления
  • APIView — базовый класс.
  • GenericAPIView + миксины (ListModelMixin, CreateModelMixin).
  • ListCreateAPIView, RetrieveUpdateDestroyAPIView — готовые CRUD-классы.
from rest_framework.generics import ListCreateAPIView

class ArticleList(ListCreateAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer

Роутеры и автоматическая маршрутизация

from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet

router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
urlpatterns = router.urls

ViewSet объединяет действия:

from rest_framework.viewsets import ModelViewSet

class ArticleViewSet(ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer

Аутентификация и разрешения

  • Authentication classesSessionAuthentication, TokenAuthentication, JWTAuthentication.
  • Permission classesIsAuthenticated, IsAdminUser, DjangoModelPermissions.

Настройка по умолчанию в settings.py:

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}

18. Асинхронные возможности

Начиная с Django 3.1, фреймворк поддерживает асинхронные представления, middleware и ORM-вызовы (с ограничениями).


Асинхронные представления

async def async_view(request):
# Асинхронный вызов внешнего API
data = await fetch_external_data()
return JsonResponse({'data': data})

Асинхронные CBV

from django.utils.decorators import classonlymethod

class AsyncView(View):
@classonlymethod
def as_view(cls, **initkwargs):
view = super().as_view(**initkwargs)
view._is_coroutine = asyncio.coroutines._is_coroutine
return view

async def get(self, request):
return JsonResponse({'status': 'ok'})

Ограничения ORM

ORM остаётся синхронной. Для асинхронного доступа к БД требуется:

  • Использовать sync_to_async:
from asgiref.sync import sync_to_async

articles = await sync_to_async(Article.objects.all)()
  • Или перейти на django-async-orm (экспериментальные решения).

ASGI-сервер

Для запуска асинхронных приложений требуется ASGI-сервер (например, Daphne, Uvicorn):

uvicorn myproject.asgi:application

19. Расширенные техники ORM

Фильтры Q и выражения F

from django.db.models import Q, F

# OR: опубликовано ИЛИ автор = текущий пользователь
Article.objects.filter(Q(is_published=True) | Q(author=user))

# сравнение полей без загрузки в Python
Article.objects.filter(views__gte=F('rating') * 10)

select_related('author') — JOIN для ForeignKey; prefetch_related('tags') — отдельный запрос для M2M и обратных FK.


Агрегация и аннотация

from django.db.models import Count, Avg

Article.objects.annotate(comment_count=Count('comments'))

Article.objects.aggregate(avg_rating=Avg('rating'))

Условные выражения

from django.db.models import Case, When, IntegerField

Article.objects.annotate(
priority=Case(
When(rating__gte=5, then=1),
default=0,
output_field=IntegerField()
)
)

Необработанные SQL-запросы

Article.objects.raw('SELECT * FROM blog_article WHERE title LIKE %s', ['%Django%'])

Или через курсор:

from django.db import connection

with connection.cursor() as cursor:
cursor.execute("UPDATE blog_article SET views = views + 1 WHERE id = %s", [pk])

PostgreSQL-специфика

Подключите django.contrib.postgres в INSTALLED_APPS. Движок БД: django.db.backends.postgresql, клиент psycopg (v3: пакет psycopg[binary]).

Поля и типы:

from django.contrib.postgres.fields import ArrayField
from django.db import models

class Tag(models.Model):
aliases = ArrayField(models.CharField(max_length=40), blank=True, default=list)

ExclusionConstraint — запрет пересекающихся диапазонов (бронь комнат, слоты):

from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import RangeOperators

class Meta:
constraints = [
ExclusionConstraint(
name='exclude_overlapping_reservation',
expressions=[
('room', RangeOperators.EQUAL),
('timeslot', RangeOperators.OVERLAPS),
],
),
]

Полнотекстовый поиск (индекс GIN):

from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank

Listing.objects.annotate(
search=SearchVector('title', weight='A') + SearchVector('content', weight='B'),
).filter(search=SearchQuery('ноутбук')).annotate(
rank=SearchRank(SearchVector('title', 'content'), SearchQuery('ноутбук')),
).order_by('-rank')

Для русского языка в SearchVector укажите config='russian'. Миграция может добавить GinIndex на выражение поиска.

См. также раздел 3-07 SQL в энциклопедии.


20. Многоязычность (i18n/l10n)

Подготовка

  • Убедиться, что USE_I18N = True
  • Загрузить LocaleMiddleware в MIDDLEWARE

Перевод в коде

from django.utils.translation import gettext as _

title = _("Welcome")

Перевод в шаблонах

{% load i18n %}
<h1>{% trans "Welcome" %}</h1>
{% blocktrans with name=user.name %}Hello {{ name }}!{% endblocktrans %}

Создание переводов

django-admin makemessages -l ru
django-admin compilemessages

Файлы .po редактируются вручную или через Poedit.


21. Email и уведомления

Отправка письма

from django.core.mail import send_mail

send_mail(
subject='Тема',
message='Текст',
from_email='admin@example.com',
recipient_list=['user@example.com'],
fail_silently=False,
)

HTML-письма

from django.core.mail import EmailMultiAlternatives

msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()

Шаблонизация писем

from django.template.loader import render_to_string

html = render_to_string('emails/welcome.html', {'user': user})

22. Фоновые задачи

Django не выполняет задачи в фоне "из коробки". Используются сторонние решения:


Celery + Redis/RabbitMQ

  • Установка: pip install celery redis
  • Создание celery.py в проекте
  • Определение задач:
from celery import shared_task

@shared_task
def send_welcome_email(user_id):
user = User.objects.get(id=user_id)
send_mail(...)
  • Вызов: send_welcome_email.delay(user.id)

Альтернативы

  • django-q
  • Huey
  • Простые cron-задачи через django-crontab

23. Мониторинг и логирование

Логирование

Конфигурация в settings.py (стандартный модуль logging Python):

Код ITЗагрузка примера кода…

Использование в коде:


import logging

logger = logging.getLogger('myapp')
logger.info('Пользователь %s вошёл', user.username)

django.request пишет трассировки при необработанных 500. В разработке SQL-запросы видны при DEBUG=True; в продакшене для медленных запросов подключают django.db.backends с уровнем DEBUG только на время диагностики.


Мониторинг

  • Sentry — сбор ошибок.
  • Prometheus + Grafana — метрики.
  • New Relic / Datadog — APM.

24. Архитектурные паттерны

Монолит

Стандартная структура Django — монолитное приложение. Подходит для MVP и средних проектов.


Микросервисы

  • Разделение на отдельные Django-проекты (API, auth, notifications).
  • Обмен через REST/gRPC.
  • Общая БД не рекомендуется.

Domain-Driven Проектирование (DDD)

  • Приложения организуются по доменным зонам (orders, payments, users).
  • Чёткое разделение слоёв: модели → сервисы → представления.

Service Layer

Вынос бизнес-логики из представлений в отдельные функции:

def create_article(title, content, author):
if Article.objects.filter(title=title).exists():
raise ValueError("Статья с таким заголовком уже существует")
return Article.objects.create(title=title, content=content, author=author)

Основа по протоколу

Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.


В подборках

Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:

СправочникиСправочник по Ext JS, Справочник по модулю Turtle, Справочник по TypeScript, Справочник по Flask, Справочник по Angular, Справочник по Python.