В этом руководстве рассмотрим как создавать пользовательские команды под фреймворк Django.
Введение
Мы пользуемся командами с тех пор, как только создали проект или приложение, а также в момент запуска сервера разработки. Команды для выполнения этих операций (startproject, startapp и runserver), вероятно самые популярные, но их гораздо больше, и мы также можем написать любую другую команду под собственные нужды.
Список команд по умолчанию доступных в нашем проекте, мы можем увидеть, запустив команду без параметров:
python3 manage.py
Или мы можем воспользоваться вторым способом
python3 manage.py help
Это список всех доступных команд по умолчанию:
А еще мы можем получить помощь для конкретной команды выполнив код:
python3 manage.py help команда
Где команда это название команды, с которой мы хотим познакомиться.
Когда необходимо создавать команду
Создание новых команд происходит, когда существующие команды не решают потребностей нашего проекта, и нам нужно сделать задачу, выполняемую время от времени (Задачи для планировщика, импорт данных из CSV и т.д.) либо автоматически, либо вручную.
Например, если какое-либо предприятие имеет систему управления персоналом, которому нужно оплачивать заработную плату, то нам нужно создать команду pay, имеющую логику производить оплату всем работникам компании.
Создание новой команды
Мы начнем работу с написания простой базовой команды. Все команды должны храниться внутри папки вашего проекта appname/management/commands/, если у вас отсутствуют эти директории, их необходимо создать.
Название будет присвоено такое же, как и у файла в котором она записана. То-есть, создав модуль под названием welcome.py, чтобы в дальнейшем выполнить эту команду необходимо ввести:
python3 manage.py welcome
Давайте проинспектируем содержимое файла welcome.py:
Команды должны наследовать от класса BaseCommand, и класс должен обязательно называться Command, так как Django будет искать по этому имени. Если мы назовем класс с другим именем, то при выполнении команды мы получим ошибку.
В атрибут help мы помещаем текст, который будет описывать, что команда делает, и именно этот текст будет показан при выполнении команды python3 manage.py help <command>. Код команды должен быть определен внутри метода handle.
Использование аргументов
Если вы читаете данную статью, скорее всего, вы создали хотя бы один проект с помощью Django, поэтому знакомы с командой startproject. Команда startproject имеет обязательный аргумент имя проекта. Пользовательские команды, также могут принимать аргументы.
Команды принимают два типа аргументов: именованные и позиционные.
Именованные аргументы это аргументы с префиксом ‘-‘ или ‘—‘ и не имеет значения, в каком порядке они будут передаваться команде.
Позиционные аргументы не имеют префикса и должны передаваться в том же порядке, в котором они заданы.
Аргументы в командах обрабатываются стандартной библиотекой Python argparse, поэтому обязаны удовлетворять ее спецификациям. Метод, называемый add_arguments, должен быть добавлен в команды, чтобы разрешить использование аргументов в пользовательской команде.
Аргумент parser является экземпляром argparse, поэтому все операции в этой библиотеке доступны и разрешены.
В случае именованных аргументов мы можем поместить «псевдонимы».
В приведенном выше примере аргумент может быть указан как «-l» или «—lastname».
Выполнение команды с аргументами, как и в предыдущем примере, производится следующим образом:
python3 manage.py welcome Egor --lastname Egorov
Аргументы со значениями по умолчанию
Для упрощения работы хочется, чтобы простой передачи аргумента было достаточно, для понимания, что делать в дальнейшем.
Например, аргумент —noreload команды runserver не требует передачи значения аргумента, так как он имеет значение по умолчанию, в данном случае значение является булевым. Если этот аргумент присутствует, значит, он имеет значение True, в противном случае это будет False. Для того чтобы создать аргумент со значением по умолчанию, при вызове метода add_argument, нам нужно добавить параметр action.
Значение параметра action будет зависеть от типа и значения по умолчанию. Если вы хотите, чтобы аргумент был булевым, то-есть при его присутствии, он должен быть True или False, он должен иметь значение store_true или store_false соответственно:
parser.add_argument('--noreload', action='store_true', help='…')
Аргументы также могут быть постоянными или делать действительно интересные вещи. Если вы обратитесь к официальной документации argparse, вы можете знать все, что можно сделать с помощью параметра action. Это пример того, как мы можем хранить константу по умолчанию:
parser.add_argument('--foo', action='store_const', const=42)
Списки аргументов
Часто мы не знаем, сколько данных будет передано нам в качестве аргумента в команду. Для решения этой проблемы существуют списки параметров, где мы можем получить список значений только с одним параметром.
Допустим, вы создаете команду для удаления пользователей, но хотите, чтобы эта команда давала возможность удалять сразу несколько пользователей. Это один из тех случаев, когда полезно использовать список аргументов.
Для создания списка необходимо добавить параметры nargs=’+’, и указать тип при вызове метода add_argument. В случае с типом параметра это может быть любой тип, принятый argparse.
Вышеуказанная команда выполняется следующим образом:
python3 manage.py remove_employee 10 9 8 7 6 5
Печать текста
Печать текста на стандартном выводе Python из команды выполняется несколько иначе, чем печать чего-либо в другом месте приложения. Вместо использования функции печати мы используем потоки stdout для стандартного вывода и stderr для ошибок. И stdout, и stderr являются атрибутами BaseCommand, поэтому мы можем использовать их следующим образом:
self.stderr.write('error') self.stdout.write('normal')
Также мы можем придать тексту цвет, используя style атрибуты. Официальная документация объясняет роль каждого из этих цветов.
Вывод
Команды являются идеальным механизмом для создания отчетов, задач обслуживания, среди прочих операций, которые периодически повторяются либо вручную, либо через запланированные задачи. Передача аргументов часто является одной из самых сложных задач при создании команд с большим количеством аргументов, а официальная документация argparse часто является идеальным местом для решения этой проблемы.
Официальная документация Django по созданию команд также является отличным ресурсом для просмотра.
Спасибо большое, очень доступно и подробно объяснили. Ни как не мог победить дз) теперь думаю справлюсь.
хорошо что помогло)
Спасибо, полезная статья!
Было бы еще неплохо узнать как запустить команду при дефолтной работе сервера (т.е не на отладочном сервере). И не через вьюху, а сразу чтобы дефолтно команда работала.
привет, Дмитрий! не совсем понятно, что ты хочешь, сразу чтобы жефолтно работала это как понять?
чтобы эта команда запускалась и работала в фоне?