Django 커스텀 커맨드 만들기

Gom La·2023년 5월 2일
0

장고와 친해지기

목록 보기
12/17
post-thumbnail

📌 Django로 커스텀 커맨드 만들기

장고 manage.py에 사용자 지정 커맨드를 만들어 사용할 수 있다.커스텀 커맨드를 작성하는 것으로 manage.py부터 사용할 수 있는 커맨드를 늘릴 수가 있다.

지금부터 원하는 기능을 커맨드로 만들어서 사용하여 보자.

  • 사용자 지정 커맨드 개요
  • 모델 만들기
  • 커맨드 작성
  • 커맨드 실행
  • 커맨드 자세히 알아보기

📌 사용자 지정 커맨드 개요

Django 커스텀 커맨드는 Django에서 생성하는 앱마다 만들 수 있으며, 커스텀 하여 만들어진 커맨드는 manage.py에서 실행할 수 있다.

예를 들어 내가 showuser라는 커맨드를 만들면 아래와 같이 사용할 수 있게된다.

python3 manage.py showuser

Django에서 관리용으로 모델을 조작하거나 참조하고 싶을 경우, 뷰를 일부러 정의하여 브라우저로 부터 실행하는 것은 매우 번거롭고, 귀찮은 일이다.

그러나 커스텀 커맨드를 만들면 커맨드 라인에서 모델, 나아가서는 전체 프로젝트를 참조 할 수 있어 매우 편리해진다.

💡 커스텀 커맨드를 만드는 cron등의 스케줄러와 조합하면 정기적으로 프로젝트를 변경하는 시스템도 구축할 수 있다.

Django 커스텀 커맨드는 설치한 앱 하위에 management라는 디렉토리를 만들고 그 아래 commands라는 디렉토리를 만든다. 그리고 커맨드명에 해당하는 모듈을 배치하고, 모듈 안에서 커맨드의 클래스를 만드는 것으로 Django가 그 커맨드를 인식한다.

➤ 명령어 생성

% python3 manage.py

Type 'manage.py help <subcommand>' for help on a specific subcommand.

Available subcommands:

[auth]
    changepassword
    createsuperuser

[contenttypes]
    remove_stale_contenttypes

[debug_toolbar]
    debugsqlshell

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata

위의 manage.py로 커맨드를 입력하면 현재 사용할 수 있는 명령어를 확인할 수 있다.
아래와 같이 management>commands>showuser.py 파일을 추가 후 동일한 폴더에 __init__.py파일을 생성 후 다시 한 번 manage.py 명령어를 확인하여 보자.

내가 생성한 showuser라는 명령어를 확인 할 수 있을 것이다.

% python3 manage.py

Type 'manage.py help <subcommand>' for help on a specific subcommand.

Available subcommands:
...
[shortener]
    showuser
...

📌 모델 만들기

커스텀 커맨드를 사용하기 위한 임의의 모델을 생성해 보자.

models.py

class User(models.Model):
    ''' 커스텀 커맨드를 위한 모델 생성 '''
    name = models.CharField(max_length=128, help_text="사용자 이름")
    content = models.TextField(max_length=1024, help_text="사용자 설명")

모델을 정의한 후 마이그레이션을 진행한다.

% python3 manage.py makemigrations
% python3 manage.py migrate

📌 커맨드 작성

커맨드로 실행하는 showuser.py파일 안에 명령어를 작성하여보자.

management>commands>showuser.py

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = 'Show user list'

    def handle(self, *args, **options):
        self.stdout.write('show user')

다음과 같이 Command 라고 하는 클래스를 만들어 준다.

이 클래스는 BaseCommand 를 상속함으로서 명령어를 이용하여 실행할 수 있게 된다.

help 속성에 커맨드의 설명을 작성하면 -h 옵션사용 시 그에 대한 설명을 확인 할 수 있다.

handle() 메소드 를 오버라이드(override)해, 커맨드가 실행되었을 때의 처리를 기입하게 한다.


📌 커맨드 실행

% python3 manage.py showuser
show user

% python3 manage.py showuser -h
usage: manage.py showuser [-h] [--version] [-v {0,1,2,3}] [--settings SETTINGS]
                          [--pythonpath PYTHONPATH] [--traceback] [--no-color]
                          [--force-color] [--skip-checks]

Show user list

options:
  -h, --help            show this help message and exit
  --version             Show program's version number and exit.
  -v {0,1,2,3}, --verbosity {0,1,2,3}
                        Verbosity level; 0=minimal output, 1=normal output,
                        2=verbose output, 3=very verbose output
  --settings SETTINGS   The Python path to a settings module, e.g.
                        "myproject.settings.main". If this isn't provided, the
                        DJANGO_SETTINGS_MODULE environment variable will be used.
  --pythonpath PYTHONPATH
                        A directory to add to the Python path, e.g.
                        "/home/djangoprojects/myproject".
  --traceback           Raise on CommandError exceptions.
  --no-color            Don't colorize the command output.
  --force-color         Force colorization of the command output.
  --skip-checks         Skip system checks.

커맨드를 실행하게 되면 본인이 작성한 코드가 실행되며 -h 옵션을 붙여 커맨드를 실행하게 되면 help 변수에 작성해 놓았던 커맨드의 설명이 출력되는 것을 확인 할 수 있다.


📌 커맨드 자세히 알아보기

➤ 표준 출력 및 표준 오류 정보

커맨드에서 표준 출력과 표준 에러를 사용하려면 self.stdout과 self.stderr를 사용하는 것이 추천되고 있다.

이러한 파일 객체를 사용하면 커맨드를 테스트하고 디버깅할 수 있다.

def handle(self, *args, **options):
	self.stdout.write('success')
    self.stderr.write('error')

또, 이러한 오브젝트의 wirte()메소드는 개행을 자동으로 부가한다. 따라서 개발자가 줄 끝에 줄 바꿈을 추가 할 필요가 없다.

개행을 제거하고 싶은 경우 print()메소드에서 사용하는 것과 동일하게 ending인수에 공문자열을 지정하면된다.

def handle(self, *args, **options):
	self.stdout.write('success', ending='')
    self.stderr.write('error', ending='')

➤ 인수 추가

커맨드는 기본적으로 인수를 사용하지 않는다. 하지만 커맨드가 인수가 필요한 경우 추가하여 커맨드를 사용할 수 있다.

from django.core.management.base import BaseCommand

from shortener.models import User

class Command(BaseCommand):
    help = 'Create user data'

    def add_arguments(self, parser):
        parser.add_argument('attrs', nargs='+', type=str)

    def handle(self, *args, **options):
        attrs = options['attrs']
        user = User.objects.create(name=attrs[0], content=attrs[1])

        self.stdout.write('Complete created user')

위와 다르게 add_arguments() 메소드가 추가되었다. 이 메소드의 parser매개변수를 이용하여
parser.add_argument를 사용하면 커맨드로 전달할 인자를 받아 handle()메소드로 전달시켜 준다.

handle() 메소드에서는 위에서 전달한 인자를 options 매개변수로 전달받아 사용자를 생성하는 데이터 처리를 진행한다.

% python3 manage.py createuser username usercontent

['username', 'usercontent']
username usercontent
Complete created user

추가로 생성한 데이터를 지워주기 위해 삭제 커맨드를 작성해 보았다.

from django.core.management.base import BaseCommand

from shortener.models import User

class Command(BaseCommand):
    help = 'Delete user data'

    def add_arguments(self, parser):
        parser.add_argument('user_id', nargs='+', type=str)

    def handle(self, *args, **options):
        users = options['user_id']
        print(users)

        for user_id in users:
            user = User.objects.filter(id=str(user_id)).last()
            user.delete()
% python3 manage.py deleteuser 3

['3']
delete user 3

➤ 옵션 추가

인수가 아닌 옵션을 통해 인자를 전달하여 명령어를 실행해보자.

from django.core.management.base import BaseCommand

from shortener.models import User

class Command(BaseCommand):
    help = 'Create user data'

    def add_arguments(self, parser):
        # parser.add_argument('attrs', nargs='+', type=str)
        parser.add_argument('-n', '--name', required=True, type=str)
        parser.add_argument('-c', '--content', required=True, type=str)

    def handle(self, *args, **options):
        # attrs = options['attrs']
        attrs = [options['name'], options['content']]

        user = User.objects.create(name=attrs[0], content=attrs[1])
        self.stdout.write('Complete created user')
% python3 manage.py createuser -n username -c usercontent

% python3 manage.py createuser --name username2 --content usercontent2

['username', 'usercontent']
Complete created user

['username2', 'usercontent2']
Complete created user

📌 참고

profile
인생 개발자 라곰!!

0개의 댓글