ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Django] custom command 만들기
    언어/파이썬 & 장고 2019. 12. 2. 19:40
    $ python3 manage.py --help

    를 입력하면 django에서 제공하는 command를 확인할 수 있습니다. 이 때, 사용자가 임의로 어떤 명령어를 만들고 해당 명령어를 통해 일련의 작업을 수행하도록 하기 위해선 커스텀 커맨드를 만들어야 합니다.

    개요

    먼저 프로젝트의 구성이 아래와 같다고 가정합니다.

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


    커스텀 커맨드를 만들기 위해선 polls와 같이 app이 지정되어야 하고 해당 app 하위에 management/commands/ 폴더가 생성되어야 합니다. 해당 폴더의 이름은 고정이며 다른 이름으로 변경할 시, 커스텀 커맨드가 작동하지 않습니다. commands 폴더 아래에 _private.py는 커스텀 커맨드로 만들 수 없으며 closepoll.py만 만들 수 있는 상태입니다. 


    위 폴더 및 파일 구조가 되었다면 closepoll.py의 내부를 아래와 같이 선언합니다.

    from polls.models import Question as Poll
    
    
    class Command(BaseCommand):
        help = 'Closes the specified poll for voting'
    
        def add_arguments(self, parser):
            # Positional arguments
            parser.add_argument('poll_ids', type=int)
    
            # Named (optional) arguments
            parser.add_argument(
                '--delete',
                type=bool,
                help='Delete poll instead of closing it',
            )
    
        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))


    먼저 클래스인 Command의 이름을 변경하면 실행이 되지 않습니다. 커스텀 커맨드를 실행하게 되면 Command 클래스의 handle() 함수가 자동으로 실행되어 해당 함수 하위에 작성된 코드를 실행 시킵니다.


    만약 커스텀 커맨드에 인수값을 추가하고 싶은 경우, add_arguments 함수를 정의해주면 됩니다. 추가할 때, 인수의 이름 앞에 --가 없으면 필수값이고 위치에 기반한 파라미터가 됩니다. --가 붙으면 이름에 기반한 optional 인수가 됩니다. ( add_argument() 에 대한 설명은 https://brownbears.tistory.com/413에서 확인할 수 있습니다.)


    즉 위와 같이 작성할 경우 실행 방법은 아래와 같습니다.

    $ python3 manage.py closepoll 10 --delete=false 
    // 성공
    
    
    $ python3 manage.py closepoll --delete=false 10
    // 성공
    
    
    $ python3 manage.py closepoll --delete=false
    // 필수값인 poll_ids가 없으므로 오류
    
    
    $ python3 manage.py closepoll poll_ids=10 --delete=false
    // 이름 기반의 인수가 아니므로 오류


    만약 콘솔 아웃풋을 찍어서 확인을 하고 싶다면 self.stdout.write()를 사용하여 확인할 수 있습니다.

    from polls.models import Question as Poll
    
    
    class Command(BaseCommand):
        def handle(self, *args, **options):
                # 터미널에서 실행 시, 색깔있는 글씨로 표현
                self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id))
                # 줄바꿈이 없으므로 다음 출력이 붙어서 출력됨
                self.stdout.write("Unterminated line", ending='')


    댓글