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