Справочник по Django
Назначение
Справочник-шпаргалка по Django — типы, синтаксис, стандартная библиотека, типовые паттерны. Не заменяет пошаговое обучение. Маршрут: первая программа → этот справочник → практикум → DRF. Обзор архитектуры — Django.
Краткое пояснение
Компоненты и ключевые особенности фреймворка.
Быстрый старт
python manage.py check --deploy
Справочные таблицы
Содержание справочника
- 1. Структура проекта Django
- 2. Настройки (settings.py)
- 3. Модели (models.py)
- 4. Представления (views.py)
- 5. Маршрутизация (URLconf)
- 6. Шаблоны (templates)
- 7. Формы (forms.py)
- 8. Административная панель (admin.py)
- 9. Миграции (migrations)
- 10. Сигналы (signals)
- 11. Middleware
- 12. Тестирование
- 13. Управление статикой и медиа
- 14. Безопасность
- 15. Производительность
- 16. Развёртывание
- 17. REST API с Django REST Framework (DRF)
- 18. Асинхронные возможности
- 19. Расширенные техники ORM
- 20. Многоязычность (i18n/l10n)
- 21. Email и уведомления
- 22. Фоновые задачи
- 23. Мониторинг и логирование
- 24. Архитектурные паттерны
- Практикум "доска объявлений" — сквозной проект после справочника
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'); - сторонние приложения;
- собственные приложения проекта.
- встроенные приложения Django (
- 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 = MyModeltemplate_name = "list.html"context_object_name = "items"— имя переменной в шаблоне.paginate_by = 10— пагинация.
-
DetailView — отображает один объект.
model = MyModeltemplate_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) |
TemplateResponseMixin | template_name, рендеринг |
SingleObjectMixin | загрузка одной записи по pk или slug |
MultipleObjectMixin | queryset списка, пагинация |
FormMixin | создание и валидация формы |
ModelFormMixin | ModelForm по полям модели |
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 %}
Сессии и cookie
Сессия — данные на сервере (или в 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.py → TEMPLATES[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) | дорогой расчёт, счётчики |
| QuerySet | cache.get_or_set('rubric_list', lambda: list(Rubric.objects.all()), 3600) | справочники |
Бэкенды в CACHES — LocMemCache (один процесс), 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 classes —
SessionAuthentication,TokenAuthentication,JWTAuthentication. - Permission classes —
IsAuthenticated,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-qHuey- Простые 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.