출처: https://meyouus.tistory.com/64 [정보 공유 - For Me For You For Us]
본문으로 바로가기

이번에는 Youtube JustDjango의 Creating a Django Boilerplate 시리즈를 해보도록 하겠다.

www.youtube.com/watch?v=qrsq8g6bqbE&list=PLLRM7ROnmA9FgFlqn-HHBz0LJ62qJBwSw&index=4


지금 어떤 종류의 Custom Commands가 필요한가?

우리는 현재 Django Boilerplate를 만들고 있다. 이 Boilerplate의 역할은 미리 준비된 Django Project를 만들어서 필요할 때마다 적용시키거나, 새로운 Django Project를 만들 때 기반이 되게끔 하여 시간을 단축시키기 위함이다. 더 자세한 사항은 여기에서 알아볼 수 있다. 우선 우리의 폴더들을 보자:

# project folder structure
src
├── demo
├── .env
├── db.sqlite3
└── manage.py


하지만 우리가 demo라는 이름의 프로젝트가 아닌 다른 이름의 프로젝트를 원한다면 어떻게 해야할 것인가?? Django가 자체적으로 프로젝트의 이름을 바꾸는 커맨드가 있으면 좋겠으나, 없으므로 우리가 새로 만들어줘야한다.


app 만들고 폴더를 구현하기

우선, core이라는 이름의 app을 하나 구현해보도록 하자:

>>> python manage.py startapp core


이렇게 한다면 다음과 같은 폴더 구조를 가지게 될 것이다:

src
├── core
├── demo
├── .env
├── db.sqlite3
└── manage.py


일단 우리가 만든 app이 제대로 구현되게 하기 위해, base.py를 수정시켜준다:

# demo/settings/base.py
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'core.apps.CoreConfig',
]
...


그리고 그 안에 management, commands, rename.py 를 순서대로 만든다:

src
├── core
│     └── management
│            └──commands
│                  └── rename.py
├── demo
├── .env
├── db.sqlite3
└── manage.py


이제 한번 powershell이나 cmd에 다음과 같이 쳐보자:

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

Available subcommands:

[auth]
    changepassword
    createsuperuser

[contenttypes]
    remove_stale_contenttypes

[core]
    rename

[debug_toolbar]
    debugsqlshell

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    sendtestemail
    shell
    showmigrations
    sqlflush
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    test
    testserver

[sessions]
    clearsessions

[staticfiles]
    collectstatic
    findstatic
    runserver


중간에 보면 [core] rename이라고 되어 있는 것을 볼 수 있을 것이다. 이 뜻은 우리가 이 rename.py에 적절한 커맨드들을 쓴다면 제대로 된 커맨드로 구현시킬 수 있다는 것이다. 이제 rename.py를 한번 구현해보자:

from django.core.management.base import BaseCommand
import os

class Command(BaseCommand):
    help = 'Renames a Django Project'

    def add_arguments(self, parser):
        parser.add_argument('new_project_name', type=str, help='The new Django Project Name')

    def handle(self, *args, **kwargs):
        new_project_name = kwargs['new_project_name']

        files_to_rename = ['demo/settings/base.py', 'demo/wsgi.py', 'manage.py']
        folder_to_rename = 'demo'

        for f in files_to_rename:
            with open(f, 'r') as file:
                filedata = file.read()

            filedata = filedata.replace('demo', new_project_name)

            with open(f, 'w') as file:
                file.write(filedata)

        os.rename(folder_to_rename, new_project_name)

        self.stdout.write(self.style.SUCCESS('Project has been renamed to %s' % new_project_name))
  1. 우선 Custom Command를 만들기 위해서는 django.core.management.base 에서 BaseCommand를 가지고 와서, Command라는 클래스에 정의를 해주어야 한다.
  2. 클래스 안의 help는 이 커맨드에 대한 정보를 알아보고 싶을 때 사용자에게 보여주기 위함이다.
  3. add_arguments(self, parser)에서 parser은 새로운 변수를 우리의 커맨드에 클래스에 추가하기 위해 있다. 'new_project_name'은 이 변수의 이름이 될 것이고, type=str은 이 변수의 종류, 즉 여기서는 문자열로 정의를 하고, 마지막의 help는 위의 help와 비슷한 용도로 사용된다.
  4. handle 함수에는 실제 이 커맨드에서 우리가 하고자 하는 로직이 들어가야 한다. 여기서 보면 handle(self, *args, **kwargs)new_project_name은 위의 add_argument 함수에서 정의한 'new_project_name'을 딕셔너리로 통과시켜준다.
  5. 다음에는 files_to_renamefolder_to_rename인데, files_to_rename 같은 경우는 우리가 바꿔야 하는 부분들, 즉 이 경우 demo라는 명칭이 들어 가 있는 중요한 파일들을 지정해주면 된다. 이 프로젝트의 경우는 base.py, wsgi.py, manage.py가 포함이 되므로 이 세가지를 포함시켜주면 된다. 확장자명까지 쓰는 것에 유의하도록 하자. folder_to_renamefiles_to_rename 이후에 정의가 되어야 하는데, 그래야 안에 있는 파일들이 먼저 이름이 바뀌고 마지막에 폴더의 이름이 바뀌면서 충돌이 일어나지 않게끔 할 수 있기 때문이다.
  6. 다음은 파일들을 읽어들이고 새로 바꿔주는 것이다. 단순한 것이므로 건너 뛰도록 하겠다.
  7. os.rename(folder_to_rename, new_project_name)는 안의 파일들이 아닌 폴더의 이름을 바꾸는 역할을 한다.
  8. 마지막으로 self.stdout.write(self.style.SUCCESS('Project has been renamed to %s' % new_project_name)) 는, powershell 또는 cmd에 성공 메세지를 출력해주는 역할을 한다.

실제로 다음과 같이 입력하면, 성공 메세지를 볼 수 있다:

>>> python manage.py rename baseapp
...
Project has been renamed to baseapp



이번 포스팅에서는 매우 간략하게 Django Custom Commands에 대해 알아보았다. 이것으로 Django Boilerplate Project는 여기서 마칠 수 있도록 하겠다.