장고로 개발할때 python manage.py <명령어> 로 명령어를 실행한다. 예를 들면 runserver, shell, shell_plus 등등..
이 명령어는 미리 지정된것만 사용할 수 있는게 아니라, 개발자가 직접 custom command를 추가할 수도 있다.
실습
1. <app_name>/management/commands 에 command 파일을 만든다. post라는 앱이 INSTALLED_APPS에 등록되어있으면, manage.py command에 test_command가 등록된다.
주의 파일명이 _로 시작한다면 manage.py command에 등록되지 않는다.
python manage.py <command_name> 을 실행하면 django.core.management call_command가 실행되는데 여기서 load_command_class 함수로 앱의 하위에 있는 command들을 가져온다.
def load_command_class(app_name, name):
"""
Given a command name and an application name, return the Command
class instance. Allow all errors raised by the import process
(ImportError, AttributeError) to propagate.
"""
module = import_module("%s.management.commands.%s" % (app_name, name)) # <app_name>/management/commands 하위의 명령어들을 가져온다.
return module.Command()
2. BaseCommand를 상속받은 Command 클래스를 만든다.
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = "Test command"
def handle(self, *args, **options):
print(options)
python manage.py test_command
3. handler에 로직을 작성한다.
from django.core.management.base import BaseCommand
from post.post_factory import PostFactory
from post.models import Post
class Command(BaseCommand):
help = "create dummy posts"
def handle(self, *args, **options):
ps = PostFactory.build_batch(1000)
Post.objects.bulk_create(ps)
4. command에 옵션을 추가할 수도 있다. add_arguments를 오버라이딩한다.
class Command(BaseCommand):
help = "hide posts"
def add_arguments(self, parser):
parser.add_argument("post_ids", nargs="+", type=int)
parser.add_argument("--exclude_deleted", action="store_true", default=False)
def handle(self, *args, **options):
posts = Post.objects.filter(id__in=options["post_ids"])
for post in posts:
if options["exclude_deleted"] and post.status == "DELETED":
raise CommandError("삭제된 게시글이 존재합니다.")
post.status = "HIDDEN"
Post.objects.bulk_update(posts, ['status'])
self.stdout.write("hide %d posts" % posts.count())
command에 옵션을 추가할 수 있는데 post_ids로 여러개 int 타입의 argument를 받을 수 있고, --exclude_deleted 를 command에 붙이면 options["exclude_deleted"] 값은 True가 된다.
python manage.py hide_posts 1 2 3 --exclude_deleted # options = {"post_ids": [1, 2, 3], "exclude_deleted": True}
parser.add_argument
- nargs:argument가 optional한지, 없거나 더 있는지(빈 배열 가능), 최소한 하나는 있는건지(빈 배열 불가) 등의 argument의 타입을 정해준다. (default면 optional이 아닌 단일값이다.) 아래 설명 참고
nargs -- The number of command-line arguments that should be consumed. By default, one argument will be consumed and a single value will be produced. Other values include: - N (an integer) consumes N arguments (and produces a list) - '?' consumes zero or one arguments - '*' consumes zero or more arguments (and produces a list) - '+' consumes one or more arguments (and produces a list) Note that the difference between the default and nargs=1 is that with the default, a single value will be produced, while with nargs=1, a list containing a single value will be produced.
# nargs 옵션 OPTIONAL = '?' ZERO_OR_MORE = '*' ONE_OR_MORE = '+' PARSER = 'A...' REMAINDER = '...'
- action: 'store', 'store_const', 'store_true', 'store_false' 액션들이 존재한다. store_true이면 옵션이 존재하면 options[옵션 이름]: True이고, False이면 False로 저장한다.
참고
https://docs.djangoproject.com/en/5.0/howto/custom-management-commands/
실습 프로젝트
https://github.com/chaeyeonhan1225/django-playground/tree/main/post_command
'Django,Python' 카테고리의 다른 글
[Django] factory_boy (2) | 2024.04.16 |
---|---|
[Python] Pickle (1) | 2024.04.06 |
[Django] on_delete=CASCADE (3) | 2024.03.23 |
[Python] 파이썬의 typing (2) | 2024.03.09 |
[Django] Template script에서 view데이터 사용하기 (1) | 2024.02.24 |