안녕하세요. 이번 시간에는 django에서 custom command를 만드는 방법을 알아봅시다.

 


 사실, python manage.py runserver라던지, 혹은 createsuperuser 등이 있어요. 이들은 command로 실행이 되는데요. package를 간단하게 보면서 어떻게 구현을 했는지만 빠르게 훑어볼 거에요. 그리고, 제 command를 간단하게 만들어 볼 거에요.

 

 

 django.auth의 management.command에 있는 changepassword.py를 보겠습니다. 이것을 보면, add_arguments와 handle이 있네요. handle의 경우에는 command가 실행되었을 때의 로직을 구현합니다. 그리고 add_arguments는 인자를 추가합니다. 이 정도만 봐도 크게 어려울 것은 없어 보입니다. add_argument 부분만 살짝 보겠습니다.

 

 첫 번째 인자로 username을 받아요. nargs가 "?"임을 주목해야 하는데요. argument가 있으면 그 값을 취하고, 없으면 default 값을 취합니다.

 

 

 그러면 logic을 수행할 때, username이 있으면 유저 이름을 얻어오고, 없으면 현재 user 정보를 얻어오게 되어 있어요.

 

 changepassword 뒤에 아무 것도 치지 않았을 때입니다. 이 때에는 41번째 줄의 else에 걸려서 getpass.getuser()가 수행되게 됩니다. 그러면 특정 argument가 없는 경우에, default 값이 설정되게 하려면 ?를 쓰는 게 좋겠네요. 예제에서 다시 보여드리겠습니다.

 


 먼저, INSTALLED_APPS에 'app'을 적습니다.

 

 

 다음에, app 밑에 management/commands를 생성합니다. commands 밑에는 sample.py를 입력해요. 이것은 sample이라는 이름을 가지는 custom 명령을 의미합니다.

 

 

 sample.py 파일을 보겠습니다. add_arguments랑 handle 2개를 추가했습니다. 먼저, add_arguments는 명령어에서의 추가 인자를 적어줍니다. 7번째 줄에 type이 int인 "limit"라는 argument를 생성했음을 알 수 있어요. 그러면 sample 명령어를 수행할 때, 인자로, int type을 받아야 한다는 의미입니다.

 

 다음에 handle이 있는데요. 이 함수 내부에 실제로 sample command가 실행되는 로직을 적습니다. 여기서 options.get("limit")라고 적었는데요. limit argument를 얻어옵니다.

 

 

 명령어 sample을 입력하고, argument로 3을 주면, 0, 1, 2를 출력함을 알 수 있습니다.

 


 그런데 argument가 없을 수도 있어요. 이럴 땐 어떻게 하면 좋을까요? 예를 들어, option을 주면 더 압축을 시켜야 하는 요구사항이 들어올 수도 있지 않겠습니까?

 

 이럴 때에는 nargs="?"를 입력하면 됩니다. 그리고, default 값까지 설정해 주면 완벽합니다.

 

 

 default 값이 1이였기 때문에, limit argument가 오지 않은 경우, 0만 출력됩니다. 만약에 limit가 2로 주어진 경우, 0과 1 2개가 출력됩니다. 여기까지 딱히 어려운 부분은 안 보이는군요. 이제 다른 예제를 생각해 봅시다. limit와 rate 이렇게 2개가 argument로 주어질 거에요.

 

 argument가 2개가 주어집니다. 하나는 limit이고 다른 하나는 rate입니다.

 

 sample 4를 입력했을 때, limit와 rate는 각각 4, 1이 나옵니다. 왜 그럴까요? 간단합니다. "?"는 소모할 수 있는 argument가 있으면 소모하고 보기 때문입니다. 문서를 보면 알 수 있어요. 소모한다는 것이 무엇인가? 4가 있어요. 그런데, limit라는 것이 먼저 들어왔단 말이죠. 4는 소모 가능하기 때문에, limit는 4라고 간주합니다.

 

 4를 소모한 후에는 아무것도 없어요. 이 시점에 rate를 보자니, 아무것도 남아 있지 않아요. 그래서, rate는 default 값인 1로 나오는 것입니다. 그러면, limit나 rate argument가 주어지지 않았을 때 처리하는 방법이 정녕 없는 것일까요?

 


 방법이 없을리가 없습니다. --limit라던지 --rate와 같이 optional argument를 주면 됩니다.

 

 

 7번째 줄과 10번째 줄이 핵심이에요. --limit와 --rate로 optional argument임을 명시했어요. 다음에 required=False로 했는데요. 반드시 필요한 필드가 아니기 때문에 False로 하였습니다. 다음, default는 --limit라던지 --rate가 없을 때 default로 무슨 값이 나오게 할 것이냐인데요. 둘 다 1로 설정했어요.

 

 

 실행 결과를 볼까요? --rate와 --limit가 둘 다 설정이 안 된 경우 1이 2번 출력됩니다. --rate만 3으로 설정된 경우, rate만 3으로, --limit만 3으로 설정된 경우 limit만 3으로 출력됩니다.