django 는 manage.py 관리 명령 을 어떻게 사용자 정의 합 니까?

Django 서 비 스 를 시작 하기 전에 저 희 는 터미널 에서 python manage.py xxx 관리 명령 을 실행 합 니 다.사실 저 희 는 관리 명령 을 사용자 정의 할 수 있 습 니 다.이것 은 독립 된 스 크 립 트 나 작업 을 수행 하 는 데 매우 유용 합 니 다.예 를 들 어 캐 시 를 지우 거나 사용자 메 일 목록 을 내 보 내 거나 메 일 을 보 내 는 등 입 니 다.
사용자 정의 관리 명령 은 manage.py 를 통 해 실 행 될 수 있 을 뿐만 아니 라 Linux 나 Celery 의 crontab 서 비 스 를 통 해 정시 작업 으로 설정 할 수 있 습 니 다.본 고 는 주로 Django-admin 명령 을 사용자 정의 하고 사례 를 보 여 주 는 방법 을 설명 한다.
사용자 정의 Django-admin 명령 은 모두 세 단계 로 나 뉘 어 있 습 니 다.폴 더 레이아웃 을 만 들 고 명령 코드 를 작성 하 며 테스트 에 사용 합 니 다.
폴 더 레이아웃 만 들 기
사용자 정의 Django-admin 관리 명령 은 본질 적 으로 python 스 크 립 트 파일 입 니 다.저장 경 로 는 일정한 규범 에 따라 야 합 니 다.일반적으로 app/management/commands 디 렉 터 리 에 있 습 니 다.전체 폴 더 의 레이아웃 은 다음 과 같 습 니 다.

 app01/
    __init__.py
    models.py
    management/
        __init__.py
        commands/
            __init__.py
            _private.py #                 
            my_commands.py #               ,        
    tests.py
    views.py
주의:
  • management 와 commands 는 디 렉 터 리 마다 가 있어 야 합 니 다.init__.py 빈 파일 은 python 패키지 임 을 표시 합 니 다.또한 아래 밑줄 친 파일 이름 은 명령 스 크 립 트 를 관리 하 는 데 사용 할 수 없습니다
  • management/commands 디 렉 터 리 는 모든 app 디 렉 터 리 에서 Django 를 찾 을 수 있 습 니 다
  • 일반적으로 python 스 크 립 트 파일 마다 관리 명령 에 대응 하 는 것 을 권장 합 니 다
  • 명령 코드 를 작성 하 다
    모든 사용자 정의 관리 명령 의 본질은 Command 클래스 입 니 다.Django 의 Basecommand 나 하위 클래스 를 계승 하여 handle()방법 으로 자신의 업무 논리 코드 를 재 작성 합 니 다.addarguments()는 명령 행 을 처리 하 는 데 도움 을 주 는 인자 입 니 다.명령 을 실행 할 때 추가 인자 가 필요 하지 않 으 면 이 방법 을 쓰 지 않 아 도 됩 니 다.
    
     from django.core.management.base import BaseCommand
     
     class Command(BaseCommand):
         #     ,               。
         help = 'Some help texts'
     
         #        ,  
         def add_arguments(self, parser):
            pass
     
         #       
         def handle(self, *args, **options):
             pass
    우 리 는 지금 가장 간단 한 예 를 보 겠 습 니 다.hello 라 는 이름 을 정의 하고 싶 습 니 다.월 드 의 명령.이렇게 하면 python manage.py hello 를 실행 합 니 다.World 명령 시 콘 솔 에서 Hello World 를 출력 합 니 다!글씨체.app/management/commands 디 렉 터 리 에 hello 새로 만 들 기world.py,다음 코드 추가:
    
     from django.core.management.base import BaseCommand
     
     class Command(BaseCommand):
        #     ,               。
        help = "Print Hello World!"
     
        #       
        def handle(self, *args, **options):
            self.stdout.write('Hello World!')
    메모:관리 명령 을 사용 하고 콘 솔 에서 지정 한 정 보 를 출력 하려 면 self.stdout 과 self.stderr 방법 을 사용 해 야 합 니 다.python 의 print 방법 을 직접 사용 할 수 없습니다.또한 메시지 의 끝 에 줄 바 꿈 자 를 붙 일 필요 가 없습니다.자동 으로 추 가 됩 니 다.
    이 때 프로젝트 폴 더 에 들 어가 python manage.py hello 를 실행 합 니 다.World 명령 시 다음 출력 결 과 를 얻 을 수 있 습 니 다:

    이제 우 리 는 난이 도 를 높 여 명령 행 을 통 해 hello 에 게World 명령 은 python manage.py helloworld John 명령 을 실행 할 때 Hello World 를 출력 하기 위해 name 인 자 를 전달 합 니 다!John。
    이제 우리 hello 수정world.py,add 추가arguments 방법,이 방법 은 사용자 정의 handle 방법 에 1 개 이상 의 인 자 를 추가 하 는 역할 을 합 니 다.
    
     from django.core.management.base import BaseCommand
     
     class Command(BaseCommand):
        #     ,               。
        help = "Print Hello World!"
     
        #          name   
        def add_arguments(self, parser):
            parser.add_argument('name')
     
        #       ,  options    name   ,        
        def handle(self, *args, **options):
            msg = 'Hello World ! '+ options['name']
            self.stdout.write(msg)
    이 때 python manage.py hello 를 다시 실행 하면World John 명령 을 내 릴 때 다음 과 같은 출력 결 과 를 얻 을 수 있 습 니 다.

    파 라 메 터 를 가지 고 있 지 않 고 명령 을 직접 실행 하면 오류 가 발생 합 니 다.다음 과 같 습 니 다.

    실제 응용 장면
    앞의 사례 는 너무 간단 합 니 다.사용자 정의 관리 명령 의 실제 응용 사례 를 살 펴 보 겠 습 니 다.
    사례 1:데이터베이스 연결 이 완료 되 었 는 지 확인
    일반적인 방식 을 사용 하 든 Docker 가 생산 환경 에 Django 프로젝트 를 배치 하 든 데이터베이스 연결 이 완 료 된 후에 야 데이터베이스 이전(migrate)명령(Docker-compose 의 depends 옵션 은 이 점 을 확보 할 수 없습니다)을 해 야 합 니 다.그렇지 않 으 면 Django 응용 프로그램 에 오류 가 발생 할 수 있 습 니 다.
    이 때 는 wait 를 사용자 정의 할 수 있 습 니 다.for_db 의 명령 은 다음 과 같다.
    
     # app/management/commands/wait_for_db.py
     
     import time
     from django.db import connections
     from django.db.utils import OperationalError
     from django.core.management import BaseCommand
     
     
     class Command(BaseCommand):
         help = 'Run data migrations until db is available.'
     
         def handle(self, *args, **options):
             self.stdout.write('Waiting for database...')
             db_conn = None
             while not db_conn:
                 try:
                     #     
                     db_conn = connections['default']
                 except OperationalError:
                     #     ,   1  
                     self.stdout.write('Database unavailable, waiting 1 second...')
                     time.sleep(1)
     
             self.stdout.write(self.style.SUCCESS('Database available!'))
    이 명령 을 정의 한 후 python manage.py migrate 명령 을 실행 하기 전에 python manage.py wait 을 실행 합 니 다.for_db 면 됩 니 다.
    사례 2:주기 적 으로 메 일 발송
    만약 당신 이 사이트 관리자 라면,매일 얼마나 많은 새로운 사용자 가 등록 되 어 있 는 지 알 고 싶 을 것 입 니 다.이 때 는 mail 을 사용자 정의 할 수 있 습 니 다.admin 의 관리 명령 은 매일 새로운 가입 사용자 수 를 메 일 로 자신 에 게 보 냅 니 다.다음 과 같 습 니 다.
    
     # app/management/commands/mail_admin.py
     
     #-*- coding:utf-8 -*-
     from datetime import timedelta, time, datetime
     from django.core.mail import mail_admins
     from django.core.management import BaseCommand
     from django.utils import timezone
     from django.contrib.auth import get_user_model
     
     User = get_user_model()
     
     today = timezone.now()
     yesterday = today - timedelta(1)
     
     
     class Command(BaseCommand):
         help = "Send The Daily Count of New Users to Admins"
     
         def handle(self, *args, **options):
             #             
             user_count =User.objects.filter(date_joined__range=(yesterday, today)).count()
             
             #          1 ,         
             if user_count >= 1:
                 message = "You have got {} user(s) in the past 24 hours".format(user_count)
     
                 subject = (
                     f"New user count for {today.strftime('%Y-%m-%d')}: {user_count}"
                )
     
                 mail_admins(subject=subject, message=message, html_message=None)
     
                 self.stdout.write("E-mail was sent.")
             else:
                 self.stdout.write("No new users today.")
    터미널 에서 python manage.py mail 을 실행 하면admin 명령,다음 출력 결 과 를 얻 을 수 있 습 니 다:

    메모:메 일 을 보 내 는 데 성공 하려 면 이메일 배경 과 관리 자 를 설정 해 야 합 니 다.테스트 환경 에서 다음 과 같은 간단 한 설정 을 사용 할 수 있 습 니 다.
    
     EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
     DEFAULT_FROM_EMAIL = "[email protected]"
     ADMINS = [("   ", "[email protected]"), ]
    그러나 매일 터미널 에 들 어가 서 이 명령 을 실행 하 는 것 이 너무 번 거 롭 습 니 다.우 리 는 Linux 의 crontab 서비스 나 Celery-Beat 를 사용 하여 주기 적 인 정시 작업 task 로 설정 할 수 있 습 니 다.이 때 는 Django 의 call 만 호출 할 수 있 습 니 다.command 방법 이면 됩 니 다.
    
     # app/tasks.py,     app     task
     from celery import shared_task
     from django.core.management import call_command
     
     @shared_task
     def mail_admin():
         call_command("mail_admin", )
    Django 프로젝트 에서 Celery 를 어떻게 사용 하여 비동기 와 주기 적 인 임 무 를 수행 하 는 지 에 대해 다음 Django 진급-비동기 와 주기 적 인 임무 편 에 참가 하 십시오.
    다음은 django 가 manage.py 관리 명령 을 어떻게 사용자 정의 하 는 지 에 대한 상세 한 내용 입 니 다.django 사용자 정의 manage.py 관리 명령 에 관 한 자 료 는 다른 글 을 주목 하 십시오!

    좋은 웹페이지 즐겨찾기