본문으로 바로가기

custom django-admin commands

category Django, Flask/🔫 Django 2020. 5. 13. 13:08

우리는 Django 서버를 돌리기 위 python manage.py runserver를 돌려왔다. 이제는 이러한 명령어를 직접 만들어보자. 

 

 

Writing custom django-admin commands | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

명령어 클래스는 BaseCommand를 상속해야 한다. BaseCommand를 살펴보면 (base.py에 이미 설명이 다 잘 되어 있다)

다음과 같이 안내해주고 있다.

    """
    The base class from which all management commands ultimately
    derive.

    Use this class if you want access to all of the mechanisms which
    parse the command-line arguments and work out what code to call in
    response; if you don't need to change any of that behavior,
    consider using one of the subclasses defined in this file.

    If you are interested in overriding/customizing various aspects of
    the command-parsing and -execution behavior, the normal flow works
    as follows:

    1. ``django-admin`` or ``manage.py`` loads the command class
       and calls its ``run_from_argv()`` method.

    .... 중략

 

뭔가 궁금하거나 새로운 기능을 넣고 싶을 때는 공식 문서나 base.py를 참고하면 된다.

 


 

python manage.py loveyou --times 5 를 입력하면 love you를 5번 출력하는 명령어를 만들어 보도록하자.

 

1. 우선 startapp을 통해 설정한 app 아무 곳에나 (사실 명령어가 영향을 미칠 적절한 app에 넣어주는 게 맞지만 시험삼아 해보는 테스트이니까 아무 곳에나...) management 폴더를 생성 한 후 __init__.py를 만들어주고, 그 폴더 내부에 commands 폴더를 생성 한 후 __init__.py를 생성해주면 된다. 

 

해당 폴더 이름들은 프레임워크의 규칙이므로 무조건 따라야 합니다.

 

To do this, add a management/commands directory to the application. Django will register a manage.py command for each Python module in that directory whose name doesn’t begin with an underscore. For example:

 

 

 

2. 이제 commands 폴더 내부에 우리가 만든 명령어인 loveyou.py를 만든 후 다음과 같이 작성해주자. BaseCommand는 커맨드를 만들기 위해 반드시 상속해야 할 것이다.

 

from django.core.management.base import BaseCommand


class Command(BaseCommand):

    pass


 

3. python manage.py loveyou를 입력하면 handle() 메서드가 없다고 오류를 낸다.

'subclasses of BaseCommand must provide a handle() method'

 

base.py에 있는 BaseCommand 클래스를 직접 살펴 보면 다음과 같이 잘 설명 되어 있다.

 

    def handle(self, *args, **options):
        """
        The actual logic of the command. Subclasses must implement
        this method.
        """
        raise NotImplementedError('subclasses of BaseCommand must provide a handle() method')

 

이를 이용하여 다음과 같이 작성해보았다.

 

from django.core.management.base import BaseCommand


class Command(BaseCommand):

    help = 'this command tell you love you'

    def add_arguments(self, parser):

        parser.add_argument("--times", help="How many times?")

    def handle(self, *args, **options):
        print(args, options)
        print("i love you")

 

이제 python manage.py loveyou --times 5를 입력하면 출력 결과는 다음과 같이 나온다.

 

()

{'verbosity': 1, 'settings': None, 'pythonpath': None, 'traceback': False, 'no_color': False, 'force_color': False, 'times': '5'}


i love you

 

5번 출력이 되게 해야하므로 handle 함수를 다음과 같이 수정해주었다.

    def handle(self, *args, **options):
        print("i love you\n" * int(options.get("times")))

 

이제 명령어는 정상적으로 작동한다!

 

추가로, 다음과 같이 BaseCommand.style 을 줘서 출력하면, 파랑 글씨로 출력할 수도 있다. 

문제는 윈도우에서는 보이지 않는다...

self.stdout.write(self.style.SUCCESS("I LOVE YOU\n") * int(options["times"]))

darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체