只有当Django开始ONCE时执行代码?

我正在编写一个Django中间件类,我只想在启动时执行一次,以初始化其他一些代码。 我跟着sdolan发布的非常好的解决scheme,但是“Hello”消息被输出到terminal两次 。 例如

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并请求一个页面时,我进入了terminal

 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 

任何想法为什么“你好世界”打印两次? 谢谢。

从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 

file: 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有一些技巧来validation模型第一等…正常部署,甚至当runserver自动重新加载,这只能执行一次。

这个问题在Django项目的博客post入口钩子中得到了很好的回答,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() 

如果有人帮忙,除了pykler的回答,“–noreload”选项会阻止runserver在启动时执行两次命令:

 python manage.py runserver --noreload 

但是,在其他代码更改后,该命令也不会重新加载runserver。

请注意,您不能可靠地连接到数据库或与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 

显然,这个解决scheme是为每个数据库连接运行一次代码,而不是每个项目启动一次。 所以你需要为CONN_MAX_AGE设置一个合理的值,所以你不会在每个请求上重新运行初始化代码。 另请注意,开发服务器会忽略CONN_MAX_AGE ,因此您将在开发中针对每个请求运行一次代码。

99%的时间这是一个坏主意 – 数据库初始化代码应该进行迁移 – 但有一些使用情况,你不能避免后期初始化,上面的警告是可以接受的。