시작시 한 번만 실행하여 다른 임의의 코드를 초기화하려는 Django Middleware 클래스를 작성 중입니다. 여기 에 sdolan이 게시 한 매우 훌륭한 솔루션을 따랐 지만 “Hello”메시지가 터미널에 두 번 출력됩니다 . 예 :
from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings
class StartupMiddleware(object):
def __init__(self):
print "Hello world"
raise MiddlewareNotUsed('Startup complete')
Django 설정 파일에서 클래스가 MIDDLEWARE_CLASSES
목록에 포함되어 있습니다.
그러나 runserver를 사용하여 Django를 실행하고 페이지를 요청하면 터미널에 도착합니다.
Django version 1.3, using settings 'config.server'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Hello world
[22/Jul/2011 15:54:36] "GET / HTTP/1.1" 200 698
Hello world
[22/Jul/2011 15:54:36] "GET /static/css/base.css HTTP/1.1" 200 0
“Hello world”가 두 번 인쇄되는 이유가 있습니까? 감사.
답변
Pykler의 답변 아래 업데이트 : Django 1.7에 이제 후크가 있습니다.
이런 식으로하지 마십시오.
한 번의 시작으로 “미들웨어”를 원하지 않습니다.
최상위 레벨에서 코드를 실행하려고합니다 urls.py
. 해당 모듈을 가져오고 한 번 실행합니다.
urls.py
from django.confs.urls.defaults import *
from my_app import one_time_startup
urlpatterns = ...
one_time_startup()
답변
업데이트 : Django 1.7에는 이제이 후크가 있습니다.
파일: myapp/apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'myapp'
verbose_name = "My Application"
def ready(self):
pass # startup code here
파일: myapp/__init__.py
default_app_config = 'myapp.apps.MyAppConfig'
장고 <1.7
첫 번째 답변은 더 이상 작동하지 않는 것 같습니다. urls.py는 첫 번째 요청시로드됩니다.
최근에 작동 한 것은 시작 코드를 INSTALLED_APPS init .py 중 하나에 넣는 것입니다.myapp/__init__.py
def startup():
pass # load a big thing
startup()
./manage.py runserver
…를 사용할 때 이것은 두 번 실행되지만 runserver에는 모델을 먼저 검증하는 트릭이 있습니다 … 정상 배포 또는 runserver 자동 다시로드 할 때도 한 번만 실행됩니다.
답변
이 질문은 Django> = 1.4에서 작동하는 Django 프로젝트 의 블로그 게시물 진입 점 후크 에서 잘 대답됩니다 .
기본적으로이를 사용 <project>/wsgi.py
하여 서버를 시작할 때 한 번만 실행되지만 명령을 실행하거나 특정 모듈을 가져올 때는 실행되지 않습니다.
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
# Run startup code!
....
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
답변
pykler의 답변 외에도 “–noreload”옵션을 사용하면 시작시 runserver가 명령을 두 번 실행할 수 없습니다.
python manage.py runserver --noreload
그러나이 명령은 다른 코드 변경 후에도 실행 서버를 다시로드하지 않습니다.
답변
@Pykler가 제안한 것처럼 Django 1.7 이상에서는 그의 답변에 설명 된 후크를 사용해야하지만 실행 서버가 호출 될 때만 (그리고 마이그레이션, 마이그레이션, 셸 등을 호출 할 때가 아닌) 함수가 호출되도록하려면 ), AppRegistryNotReady 예외 를 피하려면 다음과 같이해야합니다.
파일: myapp/apps.py
import sys
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'my_app'
def ready(self):
if 'runserver' not in sys.argv:
return True
# you must import your modules here
# to avoid AppRegistryNotReady exception
from .models import MyModel
# startup code here
답변
당신이주의 할 수없는 내부 모델 데이터베이스 또는 상호 작용에 연결 신뢰성 AppConfig.ready
기능을합니다 (참조 경고 워드 프로세서를).
시작 코드에서 데이터베이스와 상호 작용해야하는 경우 데이터베이스 connection_created
에 연결할 때 신호를 사용하여 초기화 코드를 실행할 수 있습니다.
from django.dispatch import receiver
from django.db.backends.signals import connection_created
@receiver(connection_created)
def my_receiver(connection, **kwargs):
with connection.cursor() as cursor:
# do something to the database
분명히이 솔루션은 프로젝트 시작 당 한 번이 아니라 데이터베이스 연결 당 한 번만 코드를 실행하기위한 것입니다. 따라서 CONN_MAX_AGE
설정에 적절한 값을 원 하므로 모든 요청에서 초기화 코드를 다시 실행하지 않아도됩니다. 또한 개발 서버는를 무시 CONN_MAX_AGE
하므로 개발 요청마다 코드를 한 번씩 실행합니다.
99 %의 시간은 나쁜 생각입니다. 데이터베이스 초기화 코드는 마이그레이션에 들어가야합니다. 그러나 늦은 초기화를 피할 수없고 위의 경고를 수용 할 수있는 사용 사례가 있습니다.
답변
서버를 실행할 때 “hello world”를 한 번 인쇄하려면 StartupMiddleware 클래스에서 print ( “hello world”)를 넣습니다.
from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings
class StartupMiddleware(object):
def __init__(self):
#print "Hello world"
raise MiddlewareNotUsed('Startup complete')
print "Hello world"