앞서서 짯던 소스코드는 테스트 소스코드고 이제 실제 커스텀 명령을 실행할 소스코드를 짜볼게요.
core
앱 아래
management 폴더를 만들고 그 안에 commands 폴더와 __init__.py을 각각 만들게요.
그리고 commands폴더 내부에 __init__.py을 다시 만들고 wait_for_db.py
파일을 생성하도록 할게요.
import time
from django.db import connections
from django.db.utils import OperationalError
from django.core.management.base import BaseCommand
class Command(BaseCommand):
"""Django command to pause execution until database 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:
self.stdout.write('Database unavailable, waiting 1 second...')
time.sleep(1)
self.stdout.write(self.style.SUCCESS('Database available!'))
처음, time
을 임포트할게요.
두 번째, 다음 django.db 패키지의 connections
모듈을 임포트합니다.
세 번째, db와의 연결이 available하지 않다면 오류를 발생시키기 위한 클래스를 임포트 할게요. from django.db.utils import OperationalError
네 번째, custom command
빌드를 위해서 'BaseCommand'를 임포트할게요.
import time
from django.db import connections
from django.db.utils import OperationalError
from django.core.management.base import BaseCommand
BaseCommand
를 상속받아서 Command클래스를 작성하겠습니다.
참고로 Docstring 작성은 항상 좋은 습관이니 짧게라도 작성해주세요.
또한 Commnad 클래스, handle 메소드의 이름은 변경하면 안되요. 장고에서 fixing해둔 이름이기 때문이에.
handle()
메소드는 아래와 같이 공식 문서에서 언급하고 있어요.
단순히 실제적인 로직을 구현하는 메서드라고 보시면 될 것 같아요.
BaseCommand.handle(*args, **options)
The actual logic of the command. Subclasses must implement this method.
It may return a Unicode string which will be printed to stdout (wrapped by BEGIN; and COMMIT; if output_transaction is True).
self.stdout.write('Waiting for database...')
코드는 화면에 메시지를 띄워주게 만들어요.
db_connn 변수를 만들고 값은 None으로 할게요.
while not db_conn:
은 db_conn이 None값이 아니라 다른 값으로 할당받거나 상태가 바뀌면 끝나게되고 그렇지 않고 DB연결이 되지 않으면 계속 loop문을 실행시키게 되조.
try ... except ...문을 작성해서 OperationalError
를 잡아내도록 할게요.
connection변수는 ConnectionHandler
라는 클래스를 변수화 시킨거에요.
except OperationalError:
self.stdout.write('Database unavailable, waiting 1 second...')
time.sleep(1)
이 부분은 오류 발생시 화면에 디비 접속이 현재 불가능함을 알리며 1초기다리라고 알려줍니다. 그리고 1초 멈추게되요.
class Command(BaseCommand):
"""Django command to pause execution until database 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:
self.stdout.write('Database unavailable, waiting 1 second...')
time.sleep(1)
self.stdout.write(self.style.SUCCESS('Database available!'))