Spec-Zone.ru › Django 5.1

Как создать пользовательские команды django-admin

Приложения могут регистрировать собственные действия с помощью manage.py. Например, вы можете добавить действие manage.py для приложения Django, которое вы распространяете. В этом документе мы создадим пользовательскую команду closepoll для приложения polls из учебника.

Для этого добавьте директорию management/commands в приложение. Django зарегистрирует команду manage.py для каждого модуля Python в этой директории, имя которого не начинается с нижнего подчеркивания. Например:

polls/
    __init__.py
    models.py
    management/
        __init__.py
        commands/
            __init__.py
            _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): ...

Поскольку деактивация переводов требует доступа к настроенным параметрам, декоратор не может использоваться для команд, которые работают без настроенных параметров.

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

Информацию о том, как тестировать пользовательские команды управления, можно найти в документации по тестированию.

Переопределение команд

Django регистрирует встроенные команды, а затем ищет команды в INSTALLED_APPS в обратном порядке. Во время поиска, если имя команды дублирует уже зарегистрированную команду, новая обнаруженная команда переопределяет первую.

Другими словами, чтобы переопределить команду, новая команда должна иметь то же имя, и её приложение должно быть перед приложением переопределяемой команды в INSTALLED_APPS.

Команды управления из сторонних приложений, которые были непреднамеренно переопределены, могут быть доступны под новым именем, создав новую команду в одном из приложений вашего проекта (упорядоченного перед сторонним приложением в INSTALLED_APPS), которая импортирует Command переопределенной команды.

Объекты команд

class BaseCommand [источник]

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

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

Для наследования от класса 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

Список или кортеж тегов, например [Tags.staticfiles, Tags.models]. Проверки системы зарегистрированные в выбранных тегах будут проверяться на наличие ошибок перед выполнением команды. Значение '__all__' может использоваться для указания того, что должны быть выполнены все проверки системы. Значение по умолчанию — '__all__'.

BaseCommand.style

Атрибут, который помогает создавать цветной вывод при записи в stdout или stderr. Например:

self.stdout.write(self.style.SUCCESS("..."))

См. Цветовое выделение синтаксиса, чтобы узнать, как изменить цветовую палитру и увидеть доступные стили (используйте заглавные версии «ролей», описанных в этом разделе).

Если вы передаете параметр --no-color при запуске вашей команды, все вызовы self.style() вернут исходную строку без цвета.

BaseCommand.suppressed_base_arguments

Параметры команды по умолчанию, которые необходимо скрыть в выводе справки. Это должен быть набор имён параметров (например, '--verbosity'). Значения параметров по умолчанию для скрытых параметров всё равно передаются.

Методы

BaseCommand имеет несколько методов, которые можно переопределить, но только метод handle() должен быть реализован.

Реализация конструктора в подклассе

Если вы реализуете __init__ в своём подклассе BaseCommand, вы должны вызвать метод BaseCommand’s __init__:

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.

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, include_deployment_checks=False, fail_level=checks.ERROR, databases=None) [source]

Использует систему проверки Django для проверки всего проекта Django на возможные проблемы. Серьёзные проблемы генерируются как исключение CommandError; предупреждения выводятся в stderr; небольшие уведомления выводятся в stdout.

Если app_configs и tags оба равны None, выполняются все системные проверки, кроме связанных с развертыванием и базой данных. tags может быть списком тегов проверки, например, compatibility или models.

Вы можете передать include_deployment_checks=True для выполнения проверок развертывания и список алиасов баз данных в databases для выполнения проверок баз данных по ним.

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(returncode=1) [source]

Класс исключений, указывающий на проблему при выполнении команды управления.

Если это исключение возникает во время выполнения команды управления из консоли командной строки, оно будет перехвачено и преобразовано в хорошо отформатированное сообщение об ошибке в соответствующий поток вывода (т. е. stderr); в результате, повышение этого исключения (с осмысленным описанием ошибки) является предпочтительным способом указания того, что что-то пошло не так при выполнении команды. Оно принимает необязательный аргумент returncode для настройки кода завершения, с которым команда управления завершит свою работу, используя sys.exit().

Если команда управления вызывается из кода через call_command(), вам нужно будет перехватить исключение при необходимости.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.1/howto/custom-management-commands/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API