SW/Django

custom django-admin commands 사용하기

융잡 2013. 8. 8. 04:46

manage.py 를 사용하여 Django의 Application에 사용자 고유의 action을 등록할 수 있다. 여기서는 저번 tutorial 에서 만들었던 polls app을 위한 커스텀 명령어 closepoll 을 만들어볼 것이다. 이를 위해 management/commands 를 어플리케이션 디렉토리에 추가한다. 그러면 장고는 그 명령어들을 폴더 내의 각각의 모듈에 알아서 등록해준다.

즉 polls 앱은 아래와 같은 구조를 가질 것이다.

polls/
    __init__.py
    models.py
    management/
        __init__.py
        commands/
            __init__.py
            _private.py
            closepoll.py
    tests.py
    views.py

이렇게 하면, closepoll 명령어는 polls 어플리게이션을 포함하는 어떤 프로젝트에서도 사용가능하게 만들어질 것이다.

_private.py 모듈은 명령어 커맨드를 관리하는 역할으로서, 명령어 자체로는 사용할수 없다.
closepoll.py 모듈을 사용하기 위해 하나의 요구조건이 있는데, BaseCommand 또는 그의 sub클래스를 상속받는 Command 클래스를 재정의해야한다는 것이다.

커맨드를 구현하기 위해, polls/management/commands/closepoll.py 를 다음과 같이 편집한다.

from django.core.management.base import BaseCommand, CommandError
from polls.models import Poll

class Command(BaseCommand):
    args = ''
    help = 'Closes the specified poll for voting'

    def handle(self, *args, **options):
        for poll_id in args:
            try:
                poll = Poll.objects.get(pk=int(poll_id))
            except Poll.DoesNotExist:
                raise CommandError('Poll "%s" does not exist' % poll_id)

            poll.opened = False
            poll.save()

            self.stdout.write('Successfully closed poll "%s"' % poll_id)


  • 커맨드를 관리하면서 콘솔 결과창(디버그를 위해서든) 보기 위해, 당신은 

    stdout 와 stderr 대신에 self.stdout 와 self.stderr를 써야합니다.
    또한 ending 파라미터를 쓰지 않는 한, 개행문자가 자동으로 붙기 때문에 개행문자로 메시지를 끝낼 필요가 없습니다.

    self.stdout.write("Unterminated line", ending='')

이제 python manage.py closepoll <poll_id> 를 써서 새로운 custom command를 사용할 수 있다.

handle() 매서드는 poll_ids에 해당하는 각각의 poll.opened 들을 모두 False 로 바꿔준다.
만약 유저가 존재하지 않는 polls 에 접근한다면 CommandError 가 일어날 것이다. 다만poll.opened attribute 는 tutorial에는 존재하지 않고, polls.models.Poll이 이 예제를 위해 추가된 것이다.

주어진 poll을 닫는 것 대신 지우고 싶을 때는 굳이 추가적인 command 등록 없이 closepoll 을 변경하면 된다. 이런 커스텀 option은 반드시 option_list 에 다음처럼 추가되어야한다.

from optparse import make_option

class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--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()
        # ...

위 예제의 delete옵션은 또한 dictionary로도 접근가능하다. ex ) option['delete']
optparse 파이썬 문서로 가면 make_option 사용법에 대해 알 수 있을 것이다.

추가하자면, 모든 management commands 는 다음과 같은 default option을 받을 수도 있다.
--verbosity
--traceback.

아래는 번역 중