【问题标题】:Where to put Django startup code?Django 启动代码放在哪里?
【发布时间】:2018-11-22 00:10:51
【问题描述】:

我希望在服务器启动时执行这些代码行(开发和生产):

from django.core import management
management.call_command('syncdb', interactive=False)

将其放入settings.py 不起作用,因为它需要已经加载设置。

将它们放在视图中并从外部访问该视图也不起作用,因为有一些中间件使用数据库并且这些中间件会失败并且不允许我访问该视图。

将它们放在中间件中会起作用,但每次访问我的应用时都会调用它。一个可能的解决方案可能是创建一个完成所有工作的中间件,然后将其自身从MIDDLEWARE_CLASSES 中删除,因此不再调用它。我可以在没有太多猴子补丁的情况下做到这一点吗?

【问题讨论】:

    标签: python django django-middleware


    【解决方案1】:

    __init__ 中编写执行此操作的中间件,然后从__init__ 中提升django.core.exceptions.MiddlewareNotUsed,django 将为所有请求删除它:)。顺便说一句,__init__ 在启动时调用,而不是在第一次请求时调用,因此它不会阻止您的第一个用户。

    有关于添加启动信号的讨论,但这不会很快可用(一个主要问题是应该何时发送此信号)

    相关票证:https://code.djangoproject.com/ticket/13024

    更新: Django 1.7 包含对此的支持。 (Documentation,由票链接)

    【讨论】:

    • 感谢您的快速回复。这正是我所需要的。
    • 根据stackoverflow.com/questions/6791911/…,这可能是有问题的。建议把启动函数放在urls.py中
    • 中间件和 urls.py 都不运行管理命令的启动代码。有更好的选择吗?
    • @krizajB:请注意,这个答案是用 django 1.0 或 1.1 编写的,目前有更好的解决方案可用,也许这个解决方案在 django 1.4 中甚至不再有效。我会用更新的技术更新答案,但我最近没有做太多的 django 开发,所以如果有人知道更好的现代技术,请随时添加。
    • 这似乎在 python 1.4 中不起作用...有什么建议/解决方法吗?
    【解决方案2】:

    在 Django 1.7+ 中,如果你想运行启动代码,

    1。避免在 migrate、makemigrations、shell 会话中运行它...

    2。避免运行两次或更多次

    解决方案是:

    文件:myapp/apps.py

    from django.apps import AppConfig
    
    def startup():
        # startup code goes here
    
    class MyAppConfig(AppConfig):
        name = 'myapp'
        verbose_name = "My Application"
        def ready(self):
            import os
            if os.environ.get('RUN_MAIN'):
                startup()
    

    文件:myapp/__init__.py

    default_app_config = 'myapp.apps.MyAppConfig'
    

    这篇文章使用了来自@Pykler 和@bdoering 的建议

    【讨论】:

    • 谁来设置环境变量RUN_MAIN?
    • @binithb 显然 django 在运行时会这样做
    【解决方案3】:

    如果您同时使用 Apache/mod_wsgi,请使用以下描述的 WSGI 脚本文件:

    http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html

    激活语言翻译后添加您需要的内容。

    因此:

    import sys
    
    sys.path.insert(0, '/usr/local/django/mysite')
    
    import settings
    
    import django.core.management
    django.core.management.setup_environ(settings)
    utility = django.core.management.ManagementUtility()
    command = utility.fetch_command('runserver')
    
    command.validate()
    
    import django.conf
    import django.utils
    
    django.utils.translation.activate(django.conf.settings.LANGUAGE_CODE)
    
    # Your line here.
    django.core.management.call_command('syncdb', interactive=False)
    
    import django.core.handlers.wsgi
    
    application = django.core.handlers.wsgi.WSGIHandler()
    

    【讨论】:

    • 当我使用 twod.wsgi 时看起来会有些不同。另外,我也想在开发服务器上执行此操作。而且我不会像apache那样低级。我的想法是,我可能不想让应用程序开发人员通过 ssh 访问服务器,而是让他通过将 django 管理员放入他的启动代码中来使用它。
    【解决方案4】:

    您可以创建自定义命令并在句柄函数中编写代码。详情看这里https://docs.djangoproject.com/en/dev/howto/custom-management-commands/

    然后您可以创建一个运行 django 服务器的启动脚本,然后执行您的新自定义命令。

    【讨论】:

    • 这是一个糟糕的选择,因为它依赖于围绕服务器启动的包装脚本。如果有人忘记在没有脚本的情况下启动服务器怎么办?
    • 我同意@KillianDS。不过,还是有可能的。但是你必须使用你的包装器作为服务器的入口点,它可以是任何平台、mod_wsgi、应用引擎、龙卷风等。
    【解决方案5】:

    如果你正在使用 mod_wsgi,你可以把它放在 wsgi start 应用中

    【讨论】:

      【解决方案6】:

      以下是我如何解决 Django 缺少的启动信号: https://github.com/lsaffre/djangosite/blob/master/djangosite/models.py 那里调用的代码特定于我的 djangosite 项目,但是通过编写一个特殊的应用程序(基于 Ross McFarland 的想法)来调用它的技巧应该适用于其他环境。 卢克

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-08
        • 2014-11-21
        • 2015-10-31
        • 1970-01-01
        • 2018-04-15
        • 1970-01-01
        • 2015-09-19
        相关资源
        最近更新 更多