Django启动时只执行代码一次?
我正在写一个Django的中间件类,希望它在启动时只执行一次,用来初始化一些其他的代码。我参考了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”会打印两次呢?谢谢。
11 个回答
47
这个问题在博客文章Django项目的入口点钩子中有很好的解答,适用于Django版本1.4及以上。
简单来说,你可以使用<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()
351
更新: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'
对于 Django 版本小于 1.7
第一种答案似乎不再有效,urls.py 文件在第一次请求时就会被加载。
最近有效的方法是把启动代码放在你任何一个 INSTALLED_APPS 的 init.py 文件里,比如 myapp/__init__.py
。
def startup():
pass # load a big thing
startup()
当你使用 ./manage.py runserver
启动时,这段代码会执行两次,但这是因为 runserver 有一些技巧,比如先验证模型等等……正常的部署或者当 runserver 自动重载时,这段代码只会执行一次。
145
来自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()