Escrevendo comandos do Django Admin personalizadosLink para este cabeçalho
Os aplicativos podem registrar suas próprias ações com manage.py. Por exemplo, você pode querer adicionar uma ação manage.py para uma aplicação Django que você está distribuindo. Neste documento, construiremos um comando customizado closepoll para a aplicação polls do tutorial.
Pra tal, adicione um diretório management/commands a sua aplicação. O Django irá registrar um comando manage.py para cada módulo Python dentro deste diretório, cujo o nome não inicie com underscore. Por exemplo:
polls/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
_private.py
closepoll.py
tests.py
views.py
Em Python 2, tenha certeza de incluir arquivo __init__.py em ambos os diretórios management e management/commands como feito acima ou seus comandos não serão detectados.
Neste exemplo, o comando closepoll estará disponível a qualquer projeto que inclui a aplicativo polls em :setting: INSTALLED_APPS.
O módulo _private.py não estará disponível como um “management command”
O módulo closepoll.py tem apenas uma exigência – deve definir uma classe Command que se extende BaseCommand ou um dos seus subclasses.
Para implementar o comando, edite polls/management/command/closepoll.py para que fique assim:
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_id', nargs='+', type=int)
def handle(self, *args, **options):
for poll_id in options['poll_id']:
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))
O novo comando personalizado pode ser chamado usando python manage.py closepoll <poll_id>.
The handle() method takes one or more poll_ids and sets poll.opened
to False for each one. If the user referenced any nonexistent polls, a
CommandError is raised. The poll.opened attribute does not exist in
the tutorial and was added to
polls.models.Question for this example.
Aceitando argumentos opcionaisLink para este cabeçalho
O mesmo closepoll poderia ser facilmente modificado para excluir uma determinada “poll”, ao invés de fechá-lo, aceitando as opções de linha de comando adicionais. Estas opções personalizadas podem ser adicionadas no método add_arguments() como este:
class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument('poll_id', nargs='+', type=int)
# Named (optional) arguments
parser.add_argument(
'--delete',
action='store_true',
dest='delete',
default=False,
help='Delete poll instead of closing it',
)
def handle(self, *args, **options):
# ...
if options['delete']:
poll.delete()
# ...
A opção ( delete no nosso exemplo) está disponível no parâmetro dict das opções do método “hanfle()”. Veja argparse na documentaçao do Python para saber mais sobre o uso do add_argument.
Além de ser capaz de adicionar opções de linha de comando personalizada, todos comandos de gereciamento aceitam algumas opções padrão, tais como :opção:`--verbosity` e :opção:`--traceback`.
Comandos de Gerenciamento e localidadesLink para este cabeçalho
Por padrão, o método BaseCommand.execute() desativa traduções porque alguns comandos internos do Django executam várias tarefas (por exemplo, renderização de conteúdo voltado ao usuário e popular o banco de dados) que exigem uma língua neutra no projeto.
Se por algum motivo, o seu comando personalizado de gerenciamento precisar usar um local fixo, é necessário que o suporte a “locale” seja ativar e desativado manualmente no método handle() usando as funções fornecidas pelo código de apoio I18N:
from django.core.management.base import BaseCommand, CommandError
from django.utils import translation
class Command(BaseCommand):
...
can_import_settings = True
def handle(self, *args, **options):
# Activate a fixed locale, e.g. Russian
translation.activate('ru')
# Or you can activate the LANGUAGE_CODE # chosen in the settings:
from django.conf import settings
translation.activate(settings.LANGUAGE_CODE)
# Your command logic here
...
translation.deactivate()
Outra necessidade pode ser que o seu comando simplesmente deva utilizar a definição de “locale” definido no “settings” e o Django deve ser mantido sem desativá-lo. Você pode fazer isso usando a opção BaseCommand.leave_locale_alone.
Ao trabalhar nos cenários descritos acima, porém, considere que comandos de gerenciamento de sistemas em tipicamente que ser muito cuidadosos sobre o funcionamento em locais não-uniformes, de modo que você pode precisar:
Verifique se o
USE_I18Né sempreTrueao executar o comando (este é um bom exemplo dos potenciais problemas decorrentes de um ambiente de execução dinâmico que comandos do Django evitam desativando traduções).Rever o código do seu comando e o código que este chama para diferenças de comportamento quando os locais são alteradas e avaliar o seu impacto sobre o comportamento previsível de seu comando.
TestandoLink para este cabeçalho
Informações sobre como testar comandos de gerenciamento personalizado pode ser encontrada no documentação de teste.
Objetos CommandLink para este cabeçalho
- class BaseCommandLink para esta definição
A classe base a partir da qual todos os comandos de gestão, em última análise derivam.
Use esta classe se você quer acesso a todos os mecanismos que realizam o parse dos argumentos da linha de comando e verificar que código chamar em resposta; se você não precisa mudar nada deste comportamento, considere usar um desses subclasses.
Subclasssing a classe BaseCommand requer que você implemente o método handle().
AtributosLink para este cabeçalho
Todos os atributos podem ser definidos em sua classe derivada e pode ser usado nas subclasses de BaseCommand
- BaseCommand.argsLink para esta definição
A string que lista os argumentos aceitos pelo comando, adequado para o uso em mensagens de ajuda; ex., um comando que tem uma lista de nomes de aplicativos pode definir isso como ‘<app_label app_label …>’.
- BaseCommand.can_import_settingsLink para esta definição
Um booleano que indica se o comando precisa ser capaz de importar configurações do Django; Se
True,execute()irá verificar se isso é possível antes de prosseguir. O valor padrão éTrue.
- BaseCommand.helpLink para esta definição
Uma breve descrição do comando, que será impresso na mensagem de ajuda quando o usuário executar o comando
python manage.py help <command>.
- BaseCommand.missing_args_messageLink para esta definição
-
Se o seu comando define argumentos posicionais obrigatórios, você pode personalizar a mensagem de erro devolvida em caso de falta de argumentos. O padrão é a saída por
argparse(“poucos argumentos”).
- BaseCommand.option_listLink para esta definição
Esta é a lista de opções do
optparseque serão alimentados no comando doOptionParserpara análise.
- BaseCommand.output_transactionLink para esta definição
Um booleano que indica como os comandos retornam SQL “statements”; Se
True, a saída será automaticamente envolvido comBEGIN;eCOMMIT;. O valor padrão éFalse.
- BaseCommand.requires_system_checksLink para esta definição
Um booleano; Se
True, todo o projeto Django será verificado sobre potenciais problemas antes de executar o comando. O valor padrão éTrue.
- BaseCommand.leave_locale_aloneLink para esta definição
Um booleano que indica se o local definido nas configurações devem se preservado durante a execução do comando em vez de ser forçosamente definido como ‘en-us’.
O valor padrão é
False.Verifique se sabe o que você está fazendo se decidir mudar o valor dessa opção em seu comando personalizado se ele cria conteúdo de banco de dados que é sensível ao local e tal conteúdo não deve conter quaisquer traduções (como acontece por exemplo com permissões em django.contrib.auth) fazendo com que o o local diferente do padrão de fato ‘en-us’ pode causar efeitos indesejados. Veja a seção comandos de gestão e locales acima para mais detalhes.
Esta opção não pode ser
Falsequando a opçãocan_import_settingsestá definido comoFalsetambém porque a tentativa de definir a localidade precisa de acesso às configurações. Esta condição irá gerar umCommandError.
- BaseCommand.styleLink para esta definição
Um atributo de instância que ajuda a criar uma saída colorida quando se escreve no
stdoutoustderr. Por exemplo:self.stdout.write(self.style.SUCCESS('...'))Veja sintaxe-coloring para aprender como modificar a paleta de cores e ver os estilos disponíveis (use caixa-alta das versões das opções descritas nessa seção).
Se você passar a opção
--no-colorao executar o seu comando, todas as chamadasself.style()retornarão a string original sem colorir.
MétodosLink para este cabeçalho
BaseCommand tem alguns métodos que podem ser sobrescritos mas apenas o método handle() deve ser implementado.
- BaseCommand.add_arguments(parser)Link para esta definição
-
Ponto de entrada que recebe argumentos do “parser” para manipular comandos passados pela linha de comando. Comandos personalizados devem sobrescrever este método para adicionar ambos argumentos posicionais ou opicionais que sejam aceitos pelo comando. Não é necessário chamar o
super()quando for uma subclasse deBaseCommand.
- BaseCommand.get_version()Link para esta definição
Retorna a versão do Django, que deve estar correto para todos os comandos internos do Django. É possível sobrescrever este método para que comandos fornecidos pelo usuário possam retornar a sua própria versão.
- BaseCommand.execute(*args, **options)Link para esta definição
Tenta executar este comando, realizando verificações de sistemas se necessário (como controlado pelo atributo
requires_system_checks). Se o comando gerar umCommandError, este é interceptado e impresso no stderr.
- BaseCommand.handle(*args, **options)Link para esta definição
A lógica real do comando. Subclasses devem implementar este método.
Ele pode retornar uma string Unicode que será impresso para
stdout(envolvido porBEGIN;e `` COMMIT; `` seoutput_transactionforTrue).
- BaseCommand.check(app_configs=None, tags=None, display_num_errors=False)Link para esta definição
Usa a estrutura de verificação do sistema para inspecionar todo o projeto Django para os potenciais problemas. Graves problemas são levantados como
CommandError; avisos são enviados para stderr; notificações menos importantes são enviados para stdout.Se ambos
app_configsetagsforemNone, todas as verificações do sistema são realizadas. `` Tags`` pode ser uma lista tags de checagem, comocompatibilityoumodels.
Subclasses de BaseCommandLink para este cabeçalho
- class AppCommandLink para esta definição
Um comando de gestão que recebe como argumento um ou mais “labels” de aplicações instaladas, e faz alguma coisa com cada um deles.
Melhor que implementar handle(), as subclasses devem implementar :meth:` ~AppCommand.handle_app_config`, que será chamado uma vez para cada aplicação.
- AppCommand.handle_app_config(app_config, **options)Link para esta definição
Executar ações do comando para
app_config, o qual será uma instância deAppConfigcorrespondente a um label do aplicativo informado na linha de comando.
- class LabelCommandLink para esta definição
Um comando de gestão que recebe um ou mais argumentos arbitrários (“labels”) na linha de comando, e faz alguma coisa com cada um deles.
Em vez de implementar handle(), subclasses devem implementar handle_label(), que será chamado uma vez para cada etiqueta.
- LabelCommand.handle_label(label, **options)Link para esta definição
Executar ações do comando para
label, que será a string como informada na linha de comando.
- class NoArgsCommandLink para esta definição
Um comando que não recebe argumentos da linha de comando
Ao invés de implementar o handle(), subclasses devem implementar handle_noargs(); handle() que será sobrescrito para ter certeza que nenhum argumento foi passado do comando
- NoArgsCommand.handle_noargs(**options)Link para esta definição
Executar ações deste comando
Exceções de comandoLink para este cabeçalho
- exception CommandErrorLink para esta definição
A classe de exceção indica um problema ao executar um comando de gestão.
Se esta exceção é gerada durante a execução de um comando de gerenciamento chamado do console da linha de comando, ele será capturado e transformado em uma mensagem de erro devidamente impresso para a saída apropriada (isto é, stderr); como resultado, gerar essa exceção (com uma descrição sensata do erro) é a maneira preferida para indicar que algo deu errado na execução de um comando.
Se um comando de gestão é chamado do código através do call_command(), cabe a você capturar a exceção quando necessário.