【问题标题】:How to know when the database is ready in Django?如何知道数据库何时在 Django 中准备就绪?
【发布时间】:2015-11-07 17:34:07
【问题描述】:

只要数据库在 Django 中准备好,我就需要做一些事情。具体来说,我需要对 db 中的值进行一些计算并将结果填充到缓存中。

从 django 1.7 开始,application registry 可以很容易地知道应用程序或模型何时可以使用。你可以写:

from django.apps import apps

if apps.ready:
    do_some_stuff()

但是我发现模型准备好了并不代表可以查询数据库。 Django 文档说:

尽管您可以如上所述访问模型类,但请避免 在您的 ready() 实现中与数据库交互

我试图连接到post_migrate 事件。如果我正在重建数据库(例如启动测试套件),它可以工作,但如果我只是使用现有的数据库(例如使用runserver),则不会。

有没有办法知道数据库在 Django >= 1.7 中是否完全可用?

【问题讨论】:

  • 我想正确理解您的用例(特别是为什么运行服务器很重要)。您正在为迁移后任务和启动任务填充缓存,并在何时寻找合适的挂钩。这些是繁重的缓存任务(或棘手的原子性),因此您希望确保只执行一次。这是对问题的公平重述吗?

标签: django database postgresql django-orm django-signals


【解决方案1】:

我也使用 post_migrate 信号。 (如:https://github.com/mrjmad/django_badgificator/blob/master/badgificator/apps.py)。

通过阅读您的问题,我意识到它不适用于“runserver”...

【讨论】:

  • 那么您是否找到了适用于这两种情况的解决方案?
  • 您是否尝试使用“connection_created”信号?
  • 是的,也不起作用,请参阅其他答案和 cmets。
  • 我上次的回答还不清楚。如果您在进行迁移时使用 post_migrate ,而在没有迁移时使用 connexion_created ,它可能会起作用吗?想知道你有没有migration,一个简单但丑陋的方法,就是测试参数中是否有“migrate”这个词。
【解决方案2】:

您可以尝试为connection_created 信号连接接收器。

【讨论】:

  • 这个信号会在 django 连接到数据库时发出,但在它运行所有迁移之前,所以很遗憾它不会工作。
【解决方案3】:

如果我正确理解您要执行的操作,您希望在启动 runserver 时用数据库中的数据填充缓存。由于在生产环境中,runserver 不会重新加载,因此您只会填充一次缓存,直到您重新启动服务器(我什至不确定 gunicorn 的行为是否与 runserver 相同。)

所以你可能有另一种方法来更新你的缓存在启动后使用 celery 或类似的东西?为什么不使用相同的方式执行第一次运行呢?

【讨论】:

    【解决方案4】:

    您可以在导入和调用应用程序后在 wsgi.py 文件中设置代码,如下所示:

    from django.core.wsgi import get_wsgi_application
    application = get_wsgi_application()
    
    print MyModel.objects.all()[0:5]
    # Setup your startup code here since you already have access to your models
    

    我根据这个链接找到了这个答案: Entry point hook for Django projects

    【讨论】:

    • 好的,它并没有完全回答问题,但您提供的链接引导我找到正确的方法。谢谢。
    • @ThibaultJ 嘿,你是怎么解决这个问题的?我有类似的问题
    • @SyedAmmarMustafa 抱歉,这条评论已有四年多了。我不记得了,我相信现在有更好的方法可以做到这一点。
    【解决方案5】:

    project/__init__.py 中的任何代码都将在数据库准备好之后但在任何视图/url 可以访问之前在启动时运行,因此只需在__init__.py 中添加一些代码,它就会按预期运行。 post_migrate 可能是多余的,因为据我所知,您无法在应用程序运行的情况下运行迁移,如果您绝对需要它,只需在启动和调用信号时运行一个函数。

    【讨论】:

    • 除非我不明白你的回答,否则这根本不是真的。 init.py 中的代码将在 python 解释器导入包后立即运行,所以在其他任何事情之前。
    猜你喜欢
    • 2012-07-31
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2019-09-01
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 2018-03-11
    相关资源
    最近更新 更多