Создание пользовательских команд django-admin
Приложения могут регистрировать свои собственные действия с помощью manage.py. Например, вы можете добавить действие manage.py для приложения Django, которое вы распространяете. В этом документе мы создадим пользовательскую команду closepoll для приложения polls из учебника.
Для этого просто добавьте директорию management/commands в приложение. Django зарегистрирует команду manage.py для каждого модуля Python в этой директории, имя которого не начинается с нижнего подчеркивания. Например:
polls/
__init__.py
models.py
management/
commands/
_private.py
closepoll.py
tests.py
views.py
В этом примере, команда closepoll будет доступна для любого проекта, который включает приложение polls в INSTALLED_APPS.
Модуль _private.py не будет доступен как команда управления.
Модуль closepoll.py имеет только одно требование — он должен определить класс Command , который расширяет BaseCommand или один из его подклассов.
Автономные скрипты
Пользовательские команды управления особенно полезны для запуска автономных скриптов или скриптов, которые периодически выполняются из crontab UNIX или из панели управления запланированными задачами Windows.
Для реализации команды отредактируйте polls/management/commands/closepoll.py следующим образом:
from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll
class Command(BaseCommand):
help = 'Closes the specified poll for voting'
def add_arguments(self, parser):
parser.add_argument('poll_ids', nargs='+', type=int)
def handle(self, *args, **options):
for poll_id in options['poll_ids']:
try:
poll = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise CommandError('Poll "%s" does not exist' % poll_id)
poll.opened = False
poll.save()
self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id))
Примечание
При использовании команд управления и желании выводить данные в консоль, необходимо писать в self.stdout и self.stderr, а не печатать напрямую в stdout и stderr. Используя эти прокси, гораздо проще тестировать вашу пользовательскую команду. Обратите также внимание, что вам не нужно добавлять символ новой строки в сообщения, он будет автоматически добавлен, если вы не укажете параметр ending:
self.stdout.write("Unterminated line", ending='')
Новую пользовательскую команду можно вызвать, используя python manage.py closepoll
<poll_ids>.
Метод handle() принимает один или несколько poll_ids и устанавливает poll.opened в False для каждого из них. Если пользователь указал несуществующие опросы, возникает CommandError. Атрибут poll.opened не существует в учебнике и был добавлен в polls.models.Question для этого примера.
Принятие необязательных аргументов
Ту же closepoll можно легко изменить, чтобы вместо закрытия удалить заданный опрос, приняв дополнительные параметры командной строки. Эти пользовательские параметры можно добавить в метод add_arguments() следующим образом:
class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument('poll_ids', nargs='+', type=int)
# Named (optional) arguments
parser.add_argument(
'--delete',
action='store_true',
help='Delete poll instead of closing it',
)
def handle(self, *args, **options):
# ...
if options['delete']:
poll.delete()
# ...
Параметр (delete в нашем примере) доступен в параметре options словаря метода handle. См. документацию Python по argparse для получения дополнительной информации об использовании add_argument.
Помимо возможности добавления пользовательских параметров командной строки, все команды управления могут принимать некоторые стандартные параметры, такие как --verbosity и --traceback.
Команды управления и локали
По умолчанию команды управления выполняются с текущей активной локалью.
Если по какой-либо причине вашей пользовательской команде управления необходимо работать без активной локали (например, чтобы предотвратить вставку переведенного контента в базу данных), отключите переводы с помощью декоратора @no_translations на методе handle():
from django.core.management.base import BaseCommand, no_translations
class Command(BaseCommand):
...
@no_translations
def handle(self, *args, **options):
...
Поскольку отключение переводов требует доступа к настроенным параметрам, декоратор нельзя использовать для команд, работающих без настроенных параметров.
Декоратор @no_translations новый. В более старых версиях переводы отключались перед запуском команды, если атрибут команды leave_locale_alone (теперь удален) был установлен в True.
Тестирование
Справочная информация о том, как протестировать пользовательские команды управления, находится в документации по тестированию.
Переопределение команд
Django регистрирует встроенные команды, а затем ищет команды в INSTALLED_APPS в обратном порядке. Во время поиска, если имя команды дублирует уже зарегистрированную команду, вновь обнаруженная команда переопределяет первую.
Другими словами, для переопределения команды новая команда должна иметь то же имя, а её приложение должно стоять перед приложением переопределяемой команды в INSTALLED_APPS.
Команды управления из сторонних приложений, которые были непреднамеренно переопределены, можно сделать доступными под новым именем, создав новую команду в одном из приложений вашего проекта (упорядоченное перед сторонним приложением в INSTALLED_APPS), которая импортирует Command переопределённой команды.
Объекты команд
-
class BaseCommand[source]
Базовый класс, из которого в конечном итоге происходят все команды управления.
Используйте этот класс, если вам нужен доступ ко всем механизмам, которые анализируют аргументы командной строки и определяют, какой код нужно вызвать в ответ; если вам не нужно изменять это поведение, рассмотрите возможность использования одного из его подклассов.
Наследование от класса BaseCommand требует реализации метода handle().
Атрибуты
Все атрибуты можно установить в вашем производном классе и использовать в BaseCommand’s подклассах.
-
BaseCommand.help -
Краткое описание команды, которое будет выведено в сообщении справки, когда пользователь выполнит команду
python manage.py help <command>.
-
BaseCommand.missing_args_message -
Если ваша команда определяет обязательные позиционные аргументы, вы можете настроить сообщение об ошибке, возвращаемое в случае отсутствия аргументов. По умолчанию используется вывод
argparse(«слишком мало аргументов»).
-
BaseCommand.output_transaction -
Булево значение, указывающее, выводит ли команда SQL-запросы; если
True, вывод будет автоматически обернутBEGIN;иCOMMIT;. Значение по умолчанию —False.
-
BaseCommand.requires_migrations_checks -
Булево значение; если
True, команда выводит предупреждение, если набор миграций на диске не соответствует миграциям в базе данных. Предупреждение не препятствует выполнению команды. Значение по умолчанию —False.
-
BaseCommand.requires_system_checks -
Булево значение; если
True, весь проект Django будет проверен на возможные проблемы перед выполнением команды. Значение по умолчанию —True.
-
BaseCommand.style -
Атрибут, который помогает создавать цветной вывод при записи в
stdoutилиstderr. Например:self.stdout.write(self.style.SUCCESS('...'))См. Цветовое форматирование, чтобы узнать, как изменить цветовую палитру и посмотреть доступные стили (используйте заглавные версии «ролей», описанных в этом разделе).
Если вы передаете параметр
--no-colorпри запуске вашей команды, всеself.style()вызовы будут возвращать исходную строку без форматирования.
Методы
BaseCommand имеет несколько методов, которые можно переопределить, но только метод handle() должен быть реализован.
Реализация конструктора в подклассе
Если вы реализуете __init__ в своём подклассе BaseCommand, вы должны вызвать конструктор BaseCommand:
class Command(BaseCommand):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# ...
-
BaseCommand.create_parser(prog_name, subcommand, **kwargs)[source] -
Возвращает экземпляр
CommandParser, который является подклассомArgumentParserс некоторыми настройками для Django.Вы можете настроить экземпляр, переопределив этот метод и вызвав
super()сkwargsпараметрамиArgumentParser.Изменено в Django 2.2:kwargsбыл добавлен.
-
BaseCommand.add_arguments(parser)[source] -
Точка входа для добавления аргументов парсера для обработки аргументов командной строки, переданных команде. Пользовательские команды должны переопределить этот метод, чтобы добавить позиционные и необязательные аргументы, принимаемые командой. Вызов
super()не нужен при непосредственном наследовании отBaseCommand.
-
BaseCommand.get_version()[source] -
Возвращает версию Django, которая должна быть корректной для всех встроенных команд Django. Команды, предоставляемые пользователем, могут переопределить этот метод, чтобы вернуть свою собственную версию.
-
BaseCommand.execute(*args, **options)[source] -
Пытается выполнить эту команду, выполняя проверки системы, если это необходимо (как контролируется атрибутом
requires_system_checks). Если команда вызываетCommandError, она перехватывается и выводится на stderr.
Вызов команды управления в вашем коде
execute() не следует вызывать напрямую из вашего кода для выполнения команды. Используйте call_command() вместо этого.
-
BaseCommand.handle(*args, **options)[source] -
Фактическая логика команды. Подклассы должны реализовать этот метод.
Он может возвращать строку, которая будет выводиться на
stdout(оборачиваемаяBEGIN;иCOMMIT;еслиoutput_transaction-True).
-
BaseCommand.check(app_configs=None, tags=None, display_num_errors=False)[source] -
Использует систему проверок для проверки всего проекта Django на наличие потенциальных проблем. Серьезные проблемы вызываются как
CommandError; предупреждения выводятся на stderr; небольшие уведомления выводятся на stdout.Если
app_configsиtagsобаNone, выполняются все проверки системы.tagsможет быть списком тегов проверок, таких какcompatibilityилиmodels.
BaseCommand подклассы
-
class AppCommand
Команда управления, которая принимает один или несколько меток установленных приложений в качестве аргументов и выполняет что-то с каждым из них.
Вместо реализации handle(), подклассы должны реализовать handle_app_config(), который будет вызываться один раз для каждого приложения.
-
AppCommand.handle_app_config(app_config, **options) -
Выполнение действий команды для
app_config, который будет экземпляромAppConfig, соответствующим метке приложения, заданной в командной строке.
-
class LabelCommand
Команда управления, которая принимает один или несколько произвольных аргументов (меток) в командной строке и выполняет что-то с каждым из них.
Вместо реализации handle(), подклассы должны реализовать handle_label(), который будет вызываться один раз для каждой метки.
-
LabelCommand.label -
Строка, описывающая произвольные аргументы, переданные команде. Строка используется в тексте использования и сообщениях об ошибках команды. По умолчанию
'label'.
-
LabelCommand.handle_label(label, **options) -
Выполнение действий команды для
label, которая будет строкой, заданной в командной строке.
Исключения команд
-
exception CommandError[source]
Класс исключений, указывающий на проблему при выполнении команды управления.
Если это исключение возникает во время выполнения команды управления из консоли командной строки, оно будет перехвачено и превращено в хорошо отформатированное сообщение об ошибке для соответствующего потока вывода (т. е. stderr); в результате, вызов этого исключения (с осмысленным описанием ошибки) является предпочтительным способом указать, что что-то пошло не так при выполнении команды.
Если команда управления вызывается из кода через call_command(), вам нужно перехватить исключение при необходимости.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.2/howto/custom-management-commands/