Ответ
Custom Management Commands в Django — это способ расширить функциональность утилиты manage.py для автоматизации рутинных задач, связанных с вашим проектом.
Назначение
Они идеально подходят для:
- Импорта/экспорта данных: например, загрузка данных из CSV-файла в базу данных.
- Периодических задач: выполнение регулярных операций (например, очистка старых записей), которые можно запускать через
cron. - Административных скриптов: выполнение сложных действий, которые неудобно делать через админ-панель или shell.
Как создать команду
-
Внутри вашего Django-приложения создайте структуру каталогов:
management/commands/.my_app/ ├── __init__.py ├── models.py ├── management/ │ ├── __init__.py │ └── commands/ │ ├── __init__.py │ └── my_command.py └── ... -
В файле
my_command.pyсоздайте класс, унаследованный отBaseCommand.
Пример простой команды:
# my_app/management/commands/my_command.py
from django.core.management.base import BaseCommand, CommandError
from my_app.models import MyModel
class Command(BaseCommand):
# Краткое описание команды, которое будет видно в `python manage.py help`
help = 'Описание моей кастомной команды'
def add_arguments(self, parser):
# Добавление позиционных и именованных аргументов
# Использует стандартный модуль Python `argparse`
parser.add_argument('model_ids', nargs='+', type=int, help='ID моделей для обработки')
parser.add_argument('--delete', action='store_true', help='Удалить объекты вместо обновления')
def handle(self, *args, **options):
# Основная логика команды
model_ids = options['model_ids']
should_delete = options['delete']
for model_id in model_ids:
try:
model = MyModel.objects.get(pk=model_id)
if should_delete:
model.delete()
self.stdout.write(self.style.SUCCESS(f'Объект {model_id} успешно удален.'))
else:
# Какая-то логика обновления
self.stdout.write(f'Объект {model_id} обработан.')
except MyModel.DoesNotExist:
raise CommandError(f'Объект с ID "{model_id}" не найден.')
self.stdout.write(self.style.SUCCESS('Команда успешно выполнена!'))
Запуск команды
Команда запускается из терминала так же, как и стандартные команды Django:
# Вызов команды с аргументами
python manage.py my_command 1 2 3
# Вызов с флагом
python manage.py my_command 1 2 --delete Ответ 18+ 🔞
О, слушай, смотри, вот есть у тебя в Django эта штука — Custom Management Commands. Ну, это как бы расширение для твоей manage.py, чтобы автоматизировать всякую рутину, которую вручную делать — пиздец как заебало.
Зачем это вообще нужно, блядь?
Ну, например:
- Тащить данные туда-сюда: загрузить кучу записей из CSV в базу — идеально.
- Периодические дела: чистить старый хлам из базы, что-то обновлять — можно на
cronповесить и забыть. - Админские скрипты: когда через админку делать неудобно, а в shell писать — нихуя неочевидно.
Как эту магию создать, ёпта?
-
Внутри своего приложения наделай папок:
management/commands/. Главное, не проеби__init__.pyв каждой, а то Django нихуя не увидит.my_app/ ├── __init__.py ├── models.py ├── management/ │ ├── __init__.py │ └── commands/ │ ├── __init__.py │ └── my_command.py <-- вот тут наше всё └── ... -
В файле
my_command.pyпишешь класс, который наследуется отBaseCommand. Без этого — нихуя не работает.
Вот тебе пример, чтоб понятно было:
# my_app/management/commands/my_command.py
from django.core.management.base import BaseCommand, CommandError
from my_app.models import MyModel
class Command(BaseCommand):
# Описание команды, которое видно в `python manage.py help`. Пиши нормально, а не как в голову взбредёт.
help = 'Моя команда, которая делает что-то полезное, а не просто пиздит'
def add_arguments(self, parser):
# Тут настраиваешь аргументы, как в обычном argparse. Ничего нового, ебать.
parser.add_argument('model_ids', nargs='+', type=int, help='IDшники моделей, которые будем мучать')
parser.add_argument('--delete', action='store_true', help='Если передать — нихуя не обновим, а удалим нахуй')
def handle(self, *args, **options):
# А вот тут уже основная логика, ради чего всё и затевалось.
model_ids = options['model_ids']
should_delete = options['delete']
for model_id in model_ids:
try:
model = MyModel.objects.get(pk=model_id)
if should_delete:
model.delete()
self.stdout.write(self.style.SUCCESS(f'Объект {model_id} успешно отправился в пизду.'))
else:
# Делаем что-то полезное, а не просто удаляем
self.stdout.write(f'Объект {model_id} обработан. Жив, здоров.')
except MyModel.DoesNotExist:
raise CommandError(f'Объект с ID "{model_id}" не найден, ты че, слепой?')
self.stdout.write(self.style.SUCCESS('Всё, готово, расходимся!'))
Как запустить эту красоту?
Всё просто, как три копейки:
# Просто вызываем с аргументами
python manage.py my_command 1 2 3
# А можно и с флагом, чтоб удалить всё к хуям
python manage.py my_command 1 2 --delete
Вот и вся магия. Ничего сложного, зато удобно, как тёплый тапок. Главное — не забудь про __init__.py, а то будешь потом ебаться, почему не работает.