Когда вы обрабатываете HTTP-запросы в Django, вы взаимодействуете с мощным механизмом — middleware, сигналами и системой сообщений. Эти три слоя делают веб-приложения гибкими, расширяемыми и отзывчивыми.
Мы с вами рассмотрели основные этапы того, какие этапы должен пройти request на всём пути нашей request-response системы, но на самом деле каждый request проходит кучу дополнительных обработок, таких как middleware, причём каждый request делает это дважды, при "входе" и при "выходе".
Middleware — это фреймворк обработки запросов и ответов. Каждый HTTP-запрос проходит через цепочку middleware " вперёд" к view и "обратно" — к пользователю. Это похоже на слоёный пирог: каждый слой может что-то сделать с запросом или ответом.
Request ↓
┌─────────────────────────────────────────────────────────┐
│ SecurityMiddleware │
│ SessionMiddleware │
│ CommonMiddleware │
│ CsrfViewMiddleware │
│ AuthenticationMiddleware │
│ YOUR CUSTOM MIDDLEWARE │
│ MessageMiddleware │
│ Clickjacking Protection (XFrameOptionsMiddleware) │
└─────────────────────────────────────────────────────────┘
View →
← Response (тот же путь обратно)
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'main.middleware.CheckUserStatus', # ваш кастомный
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]def simple_middleware(get_response):
def middleware(request):
print("Before view")
response = get_response(request)
print("After view")
return response
return middlewareclass SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
print("Before view")
response = self.get_response(request)
print("After view")
return responseДобавьте middleware в settings.py.
Порядок имеет значение! Если вы добавили middleware, работающий с request.user, он должен быть после
AuthenticationMiddleware.
Для совместимости с устаревшими API:
from django.utils.deprecation import MiddlewareMixin
class MyMiddleware(MiddlewareMixin):
def process_request(self, request):
...
def process_response(self, request, response):
...📚 Signals
Сигналы — способ уведомить части вашего приложения о том, что «что-то произошло» — например, сохранение объекта. Это помогает разделить ответственность и не писать логику в моделях или view напрямую.
| Сигнал | Когда вызывается |
|---|---|
pre_save / post_save |
До/после сохранения объекта |
pre_delete / post_delete |
До/после удаления объекта |
m2m_changed |
Изменения в ManyToMany |
request_started / request_finished |
Начало/конец запроса |
from django.db.models.signals import post_save
from django.dispatch import receiver
from myapp.models import Order
@receiver(post_save, sender=Order)
def after_order_save(sender, instance, created, **kwargs):
if created:
send_email_to_manager(instance)from django.dispatch import Signal
pizza_done = Signal()
pizza_done.send(sender=None, toppings=["pepperoni"], size="large")- Скрытая логика: сигналы вызываются "в фоне", усложняя отладку.
- Неявные зависимости: сложно понять, кто слушает сигнал.
- Ошибки в сигналах → падает всё.
Используйте осознанно и выборочно, особенно в больших проектах.
Обычно сигналы регистрируются в отдельном модуле signals.py внутри вашего приложения, а затем подключаются в
apps.py.
myapp/
├── apps.py
├── models.py
├── signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Order
@receiver(post_save, sender=Order)
def notify_manager(sender, instance, created, **kwargs):
if created:
print(f"New order created: {instance.id}")from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'myapp'
def ready(self):
import myapp.signals📌 Метод ready() вызывается при старте Django, и именно там следует импортировать модуль с сигналами, чтобы они
были зарегистрированы. Не подключайте сигналы в models.py или __init__.py — это может привести к проблемам с
импортами.
Файл apps.py содержит класс-настройку вашего приложения и используется Django для конфигурации.
from django.apps import AppConfig
class BlogConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'blog'- Регистрировать сигналы
- Выполнять инициализацию сторонних библиотек
- Проверять зависимости
- Настраивать логгеры
- Создавать фоновые задачи или cron-хуки (например, через Celery beat)
📌 Только не загружайте ready() тяжёлыми действиями — он вызывается при каждом запуске процесса Django.
Сообщения позволяют показать одноразовое уведомление пользователю после запроса. Пример — «Вы успешно зарегистрировались».
Убедитесь, что:
'django.contrib.messages'вINSTALLED_APPS'django.contrib.messages.middleware.MessageMiddleware'вMIDDLEWAREdjango.contrib.messages.context_processors.messagesвTEMPLATES -> OPTIONS -> context_processors
from django.contrib import messages
def my_view(request):
messages.success(request, "Профиль обновлён!")
return redirect("profile")messages.debug(request, "Отладка")
messages.info(request, "Информация")
messages.success(request, "Успех!")
messages.warning(request, "Предупреждение")
messages.error(request, "Ошибка"){% if messages %}
<ul class="messages">
{% for message in messages %}
<li class="{{ message.tags }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}from django.contrib.messages.views import SuccessMessageMixin
class MyView(SuccessMessageMixin, CreateView):
success_message = "Объект успешно создан!"| Сценарий | Пример сообщения |
|---|---|
| Успешная регистрация | messages.success |
| Ошибка заполнения формы | messages.error |
| Предупреждение о балансе | messages.warning |
| Отображение отладочной info | messages.debug |
✅ Middleware — это обработчик запроса и ответа, может быть функцией или классом
✅ Signals позволяют реагировать на действия модели без изменения её кода
✅ Messages — это одноразовые уведомления, удобно использовать после redirect'ов
✅ Не забывайте включать нужные middleware и context_processors
✅ Middleware работают в двух направлениях: запрос и ответ
Manage-команды в рамках Django - это возможность запустить скрипт из консоли для выполнения абсолютно различных действий.
Существует три способа запуска manage-команды:
django-admin <command> [options]
python manage.py <command> [options]
python -m django <command> [options]
В случае запуска через django-admin вы можете указать, какой файл настроек использовать при помощи опции --settings.
Если вы запускаете команду через manage.py (самый распространенный способ), файл настроек будет выбран в соответствии
с самим файлом manage.py (Напоминаю структуру, информация о файле настроек для Django проекта находится именно в
файле manage.py).
Мы использовали некоторые команды, но давайте посмотрим подробнее.
| Категория | Команда | Описание | Пример использования |
|---|---|---|---|
| 🏗 Создание проекта и приложений | startproject |
Создает новый Django-проект | django-admin startproject mysite |
startapp |
Создает новое Django-приложение | python manage.py startapp blog |
|
| 🔄 Миграции и работа с БД | makemigrations |
Генерирует файлы миграций на основе моделей | python manage.py makemigrations users |
migrate |
Применяет миграции к базе данных | python manage.py migrate |
|
showmigrations |
Показывает все миграции и их статус | python manage.py showmigrations |
|
sqlmigrate |
Показывает SQL-код конкретной миграции | python manage.py sqlmigrate users 0001 |
|
squashmigrations |
Объединяет несколько миграций в одну | python manage.py squashmigrations users 0001 0005 |
|
flush |
Удаляет все данные из базы (сохраняя структуру) | python manage.py flush |
|
sqlflush |
Показывает SQL-код, который будет выполнен при flush | python manage.py sqlflush |
|
sqlsequencereset |
Сброс последовательностей (id) | python manage.py sqlsequencereset users |
|
inspectdb |
Генерирует модели на основе существующей БД | python manage.py inspectdb > models.py |
|
| 🧪 Тестирование | test |
Запускает unit-тесты | python manage.py test |
| 🧠 Управление пользователями | createsuperuser |
Создание суперпользователя | python manage.py createsuperuser |
changepassword |
Изменение пароля пользователя | python manage.py changepassword admin |
|
| 🌐 Сервер и консоль | runserver |
Запускает локальный сервер разработки | python manage.py runserver 8080 |
shell |
Открывает Django shell | python manage.py shell |
|
dbshell |
Открывает shell для БД (например, psql) |
python manage.py dbshell |
|
| 🗃 Работа с данными (фикстуры) | dumpdata |
Экспорт данных в JSON (фикстуры) | python manage.py dumpdata > data.json |
loaddata |
Импорт данных из JSON-файла | python manage.py loaddata data.json |
|
| 📖 Работа с переводами | makemessages |
Поиск строк для перевода (создает .po) |
python manage.py makemessages -l ru |
compilemessages |
Компиляция .po в .mo для использования |
python manage.py compilemessages |
|
| 📦 Кэш и сессии | createcachetable |
Создает таблицу в БД для хранения кэша | python manage.py createcachetable |
clearsessions |
Удаляет устаревшие сессии из БД | python manage.py clearsessions |
|
| 🔧 Отладка и администрирование | check |
Проверка проекта на ошибки конфигурации | python manage.py check |
diffsettings |
Сравнение текущих и дефолтных настроек | python manage.py diffsettings |
|
sendtestemail |
Отправка тестового письма (если email настроен) | python manage.py sendtestemail user@example.com |
|
| 📜 Пользовательские команды | (имя команды) | Кастомная команда в management/commands/ |
python manage.py close_orders |
Как создавать проект и приложения вы в целом научились, давайте посмотрим на новые команды, или как можно не стандартно использовать старые.
Уже известная вам команда, которая создаёт файлы миграций, и может принимать имя приложения, чтобы создать только для конкретного приложения.
Может принимать важный параметр --empty, при этом флаге создастся пустая миграция, никак не привязанная к моделям.
Выглядеть будет примерно вот так:
# Generated by Django 3.0.7 on 2020-10-29 11:59
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('storages', '0003_auto_20201029_1352'),
]
operations = [
]Тут указано приложение, для которого миграция будет применена, и прошлая миграция, с которой текущая миграция будет связана.
Зачем это вообще надо?
Мы можем в операции добавить любые интересующие нас действия, например, выполнения кода на Python.
Для этого нужно добавить класс RunPython из пакета migrations, который будет принимать два метода, первый будет
выполнен в случае выполнения миграции, второй - в случае отката миграции.
# Generated by Django 3.0.7 on 2020-10-29 11:59
from django.db import migrations
def some_forward_action(apps, schema_editor):
Team = apps.get_model('storages', 'Team')
Team.objects.create(name='B2B')
Team.objects.create(name='CX')
Team.objects.create(name='SFA')
def some_backward_action(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
('storages', '0003_auto_20201029_1352'),
]
operations = [
migrations.RunPython(some_forward_action, some_backward_action)
]Такие миграции называются Data Migrations.
Чаще всего для того, чтобы занести какие-либо данные в базу данных на этапе миграции, например, создать заведомо известные объекты, как в моём примере, или для установки вычисляемого значения по умолчанию.
Для обратной миграции чаще всего действия не требуются (хоть и далеко не всегда), поэтому чаще всего обратная миграция
записывается в виде лямбды lambda x, y: None
Типовая Data Migration:
# Generated by Django 3.0.7 on 2020-10-29 11:59
from django.db import migrations
def some_forward_action(apps, schema_editor):
Team = apps.get_model('storages', 'Team') # Приложение и модель
Team.objects.create(name='B2B')
Team.objects.create(name='CX')
Team.objects.create(name='SFA')
class Migration(migrations.Migration):
dependencies = [
('storages', '0003_auto_20201029_1352'),
]
operations = [
migrations.RunPython(some_forward_action, lambda x, y: None)
]Уже известная вам команда для применения миграции
Команда migrate применяется для выполнения миграций и синхронизации состояния базы данных с текущими моделями проекта.
python manage.py migrate [app_label] [migration_name]
-
app_label — имя приложения, миграции которого необходимо применить.
-
migration_name — имя конкретной миграции (обычно достаточно первых четырёх цифр из имени миграции).
Если не указать параметры, команда применит все миграции для всех приложений.
Допустим, вы уже применили миграции до 0008, но обнаружили ошибку в 0006. Вы можете откатить состояние базы данных
до миграции 0005:
python manage.py migrate my_app 0005
⚠️ Это приведёт к откату всех миграций после 0005 и, скорее всего, приведёт к потере данных, связанных с удаляемыми моделями и полями.
Флаг --fake позволяет пометить миграцию как выполненную, не внося реальные изменения в базу данных:
python manage.py migrate my_app 0005 --fakeЭтот приём используется в ситуациях, когда база данных уже была подготовлена вручную или через внешнюю систему (например переносите проект с другого фреймворка на джанго), и вы хотите синхронизировать Django с её текущим состоянием.
Если вместо номера миграции указать zero, можно откатить все миграции для указанного приложения:
python manage.py migrate my_app zero🔥 Важно: Откат миграций удалит таблицы и данные. Сделайте резервную копию!
Также уже известная вам команда, которая отобразит список миграций и их состояние (применена или нет).
Команда sqlmigrate позволяет посмотреть SQL-код, который будет сгенерирован и выполнен при применении определённой миграции. Это особенно полезно, если вы хотите:
- понять, какие структурные изменения будут внесены в базу;
- провести аудит миграций перед деплоем;
- получить SQL-запросы для ручного применения или изучения.
python manage.py sqlmigrate <app_label> <migration_name>app_label— имя приложения, напримерusers;migration_name— имя миграции без префикса0XXX_, достаточно просто0001илиinitial.
python manage.py sqlmigrate users 0001Вывод будет содержать SQL-запросы, необходимые для создания таблиц и индексов, например:
CREATE TABLE "users_user" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"username" varchar(150) NOT NULL UNIQUE,
"email" varchar(254) NOT NULL
);🔍 Совет: Используйте
sqlmigrate, чтобы убедиться, что миграции не создают неожиданных изменений, особенно если вы вносите правки вручную или используетеRunSQL.
Команда squashmigrations используется для объединения нескольких последовательных миграций в одну, чтобы упростить структуру миграций и улучшить читаемость проекта.
Это особенно полезно после активной разработки, когда в приложении накопилось множество миграций, добавляющих поля, изменяющих типы или удаляющих элементы в одной и той же модели.
python manage.py squashmigrations <app_label> <start_migration> <end_migration>Допустим, в приложении myapp имеются миграции 0004, 0005, 0006 и 0007, каждая из которых добавляет или изменяет поля в одной модели. Чтобы объединить их в одну миграцию, выполните:
python manage.py squashmigrations myapp 0004 0007Это создаст новую миграцию, содержащую совокупность всех изменений между 0004 и 0007, и заменит старые миграции.
:::tip Squash-команды следует выполнять только после того, как все предыдущие миграции были применены на всех окружениях, иначе возможны проблемы с синхронизацией структуры базы данных. :::
- После нескольких итераций разработки модели, когда накопилось много миграций.
- Перед выпуском в продакшн, чтобы упростить аудит миграций.
- Для улучшения производительности применения миграций при CI/CD.
Squash не удаляет старые миграции автоматически — вы можете проверить и при необходимости удалить их вручную после тестирования новой объединённой миграции.
Команда flush очищает базу данных от всех данных пользователя, сбрасывая содержимое всех таблиц, но не отменяя миграций и не удаляя структуру базы.
Это значит, что после выполнения команды:
- Все таблицы останутся на месте.
- Все миграции будут считаться применёнными.
- Будут удалены все данные, включая созданных пользователей, записи моделей и данные сессий.
- Значения автоинкрементных полей (
id) будут сброшены (если это поддерживает СУБД).
python manage.py flushПосле выполнения вы получите предупреждение с подтверждением:
You have requested a flush of the database.
This will IRREVERSIBLY DESTROY all data in the database.
Are you sure you want to do this?- Для быстрого сброса данных при локальной разработке.
- При подготовке к демонстрации, когда нужна «чистая» база.
- Для очистки базы перед загрузкой фикстур:
python manage.py flush
python manage.py loaddata initial_data.json
⚠️ Важно: не используйтеflushв продакшене — она удалит все данные и их восстановление будет невозможно без резервной копии.
Команда sqlflush выводит SQL-инструкции, которые будут выполнены при вызове команды flush.
Это полезно, если вы хотите:
- Предварительно увидеть, какие SQL-команды будут применены;
- Понять, какие таблицы будут очищены;
- Использовать SQL напрямую (например, для предварительного анализа или отладки).
python manage.py sqlflush
$ python manage.py sqlflush
BEGIN;
DELETE FROM "myapp_modelname";
DELETE FROM "auth_user";
DELETE FROM "django_session";
...
COMMIT;- Команда не выполняет очистку базы данных, она только печатает SQL, который бы использовался.
- Учитывает текущую конфигурацию базы данных и зарегистрированные модели.
Команда sqlsequencereset используется для сброса последовательностей автогенерации идентификаторов (например, id) в базе данных. Это важно, когда вы вручную очищаете таблицы и хотите, чтобы следующая вставка начиналась с id = 1.
python manage.py sqlsequencereset <app_label><app_label>— имя приложения Django, для которого нужно сбросить последовательности.
Например:
python manage.py sqlsequencereset blogЭта команда не вносит изменений в базу напрямую, а просто печатает SQL-код, который необходимо выполнить для сброса последовательностей. Это особенно полезно при ручной очистке таблиц с помощью flush или truncate.
Когда вы удаляете все записи из таблицы вручную (например, через DELETE FROM), следующий id по умолчанию не будет начинаться с 1, так как значение хранится в последовательности (sequence). sqlsequencereset позволяет сбросить эти sequence-объекты, чтобы обеспечить консистентность ID.
Не применяйте сброс последовательностей на продуктивной базе с пользовательскими данными. Это может привести к конфликтам ключей.
SELECT setval(pg_get_serial_sequence('"myapp_mymodel"', 'id'), COALESCE(MAX("id"), 1), max("id") IS NOT null) FROM "myapp_mymodel";Этот SQL-запрос устанавливает значение последовательности id в зависимости от текущих данных в таблице.
Команда inspectdb используется для генерации моделей Django на основе уже существующей базы данных.
Это особенно полезно, если вы начинаете работать над проектом с существующей схемой базы данных, которая ранее не использовалась с Django. Вместо того чтобы вручную описывать модели, вы можете сгенерировать их автоматически.
python manage.py inspectdbВывод будет содержать Python-код с определениями моделей, которые можно скопировать в файл models.py соответствующего приложения.
Предположим, у вас есть существующая база данных с таблицами users и orders. Выполнив команду:
python manage.py inspectdb > myapp/models.pyВы получите файл models.py с автосгенерированными моделями:
class Users(models.Model):
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=150)
email = models.EmailField()
class Meta:
managed = False
db_table = 'users'--database: имя подключения к базе данных, если используется не дефолтное (default).--include-partial: добавляет частично поддерживаемые поля.--table: позволяет указать конкретные таблицы для генерации моделей.
Пример для одной таблицы:
python manage.py inspectdb --table users- Генерируемые модели будут иметь
managed = False, что означает, что Django не будет пытаться мигрировать эти таблицы. - После генерации моделей их часто нужно вручную отредактировать: переименовать поля, добавить связи, ограничения и т. д.
- Это хороший старт, но не замена полноценного проектирования моделей вручную.
- При переносе существующего проекта (например, с PHP или Java) на Django.
- При необходимости подключиться к сторонней базе и использовать Django ORM без миграций.
- Для быстрого создания моделей для репорта или анализа на основе чужой БД.
🧠 Управление пользователями
Команда для смены пароля конкретному пользователю.
manage.py changepassword ringo
Команда для создания пользователя со всеми правами.
Команда shell запускает интерактивную Python-консоль с уже настроенной Django-средой. Это означает, что вам не нужно вручную импортировать модели, настройки и другие компоненты проекта — всё уже доступно.
Примеры использования:
python manage.py shellПолезно для:
- Ручного тестирования функций и моделей
- Временного взаимодействия с ORM
- Быстрого импорта и анализа данных
Команда dbshell открывает интерактивную консоль для работы с базой данных, указанной в настройках DATABASES.
Например, если вы используете PostgreSQL, будет открыт psql, если SQLite — обычная SQLite-консоль и т.д.
Примеры:
python manage.py dbshellПолезно для:
- Прямого выполнения SQL-запросов
- Быстрого анализа или модификации данных на низком уровне
- Отладки проблем с миграциями и схемой
Убедитесь, что нужный клиент базы данных установлен в системе (например,
psqlдля PostgreSQL,mysqlдля MySQL).
Команда runserver запускает встроенный отладочный сервер Django.
Пример:
python manage.py runserverМожно указать IP и порт:
python manage.py runserver 0.0.0.0:8000По умолчанию используется порт 8000 и адрес 127.0.0.1.
Полезно для:
- Разработки и локального тестирования приложения
- Быстрой демонстрации функциональности
⚠️ Важно:runserverне предназначен для продакшена. На боевых серверах используйте WSGI-серверы, такие как Gunicorn, uWSGI, Daphne и т. п.
Команда dumpdata используется для создания резервной копии данных из базы данных в виде JSON-файла (или в другом формате, если указать).
Это особенно полезно для:
- создания фикстур (fixtures), которые можно использовать для загрузки данных в тестовую или начальную среду;
- резервного копирования состояния отдельных приложений или моделей;
- миграции данных между проектами.
python manage.py dumpdata [app_label.ModelName] [--indent N] [--output filename.json]-
Сохранить все данные из базы:
python manage.py dumpdata > all_data.json -
Сохранить данные только из приложения
blog:python manage.py dumpdata blog > blog_data.json -
Сохранить данные из конкретной модели
Author:python manage.py dumpdata blog.Author > authors.json -
Сохранять с отступами (удобнее для чтения):
python manage.py dumpdata blog.Author --indent 2 > authors.json -
С указанием имени файла напрямую:
python manage.py dumpdata blog --output blog_data.json
Вы можете комбинировать команды с --exclude:
python manage.py dumpdata --exclude auth.permission --exclude contenttypes > data.jsonКоманда loaddata загружает данные из JSON-файла (или другого формата фикстур) обратно в базу данных.
Это особенно полезно для:
- восстановления состояния базы из резервной копии;
- начального наполнения базы данных (например, при запуске нового окружения);
- использования в тестах.
python manage.py loaddata filename.json-
Загрузка полного дампа:
python manage.py loaddata all_data.json
-
Загрузка дампа только моделей
Author:python manage.py loaddata authors.json
-
Загрузка нескольких файлов:
python manage.py loaddata file1.json file2.json
Фикстуры можно хранить в директориях fixtures/ в каждом приложении — Django их найдёт автоматически.
Важно: При загрузке данных из JSON-файла все
id, указанные в файле, будут использоваться как есть. Убедитесь, что данные не конфликтуют с уже существующими.
В Django команды makemessages и compilemessages используются для организации и управления локализацией (переводом интерфейса на разные языки).
Команда makemessages используется для создания или обновления файлов перевода (.po), которые содержат строки, подлежащие переводу.
python manage.py makemessages -l <locale> [опции]-l, --locale— язык перевода (например,fr,pt_BR,uk).--ignore— шаблон файлов, которые нужно игнорировать.--extension— расширения файлов, где следует искать переводы (по умолчанию.html,.txt,.py).--domain— можно указатьdjangojsдля перевода JS-файлов.
python manage.py makemessages -l ukЭтот вызов создаст (или обновит) файл перевода uk/LC_MESSAGES/django.po.
- В проектах с мультиязычным интерфейсом.
- При локализации текстов, сообщений и шаблонов.
- В любых Django-приложениях, где используется
gettext,ugettext, либо шаблонные теги{% trans "..." %}.
В views.py:
from django.utils.translation import gettext as _
def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)В .po файле:
msgid "Welcome to my site."
msgstr "Ласкаво просимо на мій сайт."После редактирования .po файлов необходимо скомпилировать их в .mo файлы, которые используются Django во время выполнения.
python manage.py compilemessages [опции]python manage.py compilemessagesЭта команда пройдёт по всем подкаталогам и скомпилирует .po файлы в .mo файлы.
- После каждого изменения или добавления новых переводов.
- Перед сборкой и деплоем проекта, если используется мультиязычность.
# Обнаружение строк для перевода
python manage.py makemessages -l fr
# Перевод строк вручную в файле locale/fr/LC_MESSAGES/django.po
# Компиляция перевода
python manage.py compilemessagesВажно: Убедитесь, что в
settings.pyуказана настройкаLOCALE_PATHS, чтобы Django знал, где искать переводы:LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale')]
В Django вы можете создавать собственные команды для manage.py, как и встроенные команды (migrate, runserver, makemigrations и т.д.). Это полезно для автоматизации задач: отчёты, массовые изменения в базе, уведомления и др.
Предположим, у нас есть проект пиццерии, и мы хотим, чтобы каждый день в 18:00 система проверяла заказы, которые остались в статусе "открыт", переводила их в статус "manual" и отправляла уведомление владельцу заведения.
Создаём команду close_orders внутри приложения orders:
orders/
├── __init__.py
├── models.py
├── management/
│ └── commands/
│ └── close_orders.py
├── tests.py
└── views.py
Папки
managementиcommandsдолжны быть именно с такими названиями.
from django.core.management.base import BaseCommand
from orders.models import Order
from orders.utils import send_email # примерная утилита отправки писем
class Command(BaseCommand):
help = "Close orders which weren't closed manually"
def handle(self, *args, **options):
orders = Order.objects.filter(status="opened")
if orders.exists():
orders.update(status="manual")
send_email(
subject="Unclosed orders",
message=f"You have {orders.count()} unclosed orders marked as 'manual'.",
to="owner@example.com"
)
self.stdout.write(self.style.SUCCESS("Successfully closed open orders."))
else:
self.stdout.write("No open orders to close.")Запустить команду можно вручную:
python manage.py close_ordersДобавьте в расписание cron выполнение этой команды каждый день в 18:00:
0 18 * * 1-5 /usr/bin/python3 /path/to/project/manage.py close_ordersУбедитесь, что активировано правильное виртуальное окружение, или используйте путь до интерпретатора прямо из него.
Создание кастомных manage.py команд — мощный способ автоматизировать задачи и расширить функциональность вашего проекта.

