Django:在每次启动时运行代码,但是在迁移数据库之后

时间:2017-04-13 13:42:14

标签: python django

我认为在最近的Django版本中有一个简单的答案,但我找不到它。

我有触及数据库的代码。我希望每次Django启动时都能运行它。我似乎有两个选择:

选项1。 AppConfig.ready() - 这可以工作,但也可以在创建数据库表之前运行(即在测试期间或在没有数据的情况下重新初始化应用程序时)。如果我使用它,我必须捕获多种类型的异常,并猜测原因是一个空db:

def is_db_init_error(e, table_name):
    return ("{}' doesn't exist".format(table_name) in str(e) or
            "no such table: {}".format(table_name) in str(e)
    )

try:
    # doing stuff 
except Exception as e:
    if not is_db_init_error(e, 'foo'):
        raise
    else:
        logger.warn("Skipping updating Foo object as db table doesn't exist")

选项2。使用post_migrate.connect(foo_init, sender=self) - 但这仅在我进行迁移时运行。

选项3。旧方式 - 从urls.py调用它 - 我想保留urls.py之类的内容,我认为AppConfig是一条真正的道路

到目前为止,我已经选择了选项2 - 我不喜欢选项1和选项3中的臭臭尝试/除了错误,因为urls.py成为倾销场。

然而,当我在本地开发时,选项2经常让我兴奋 - 我需要记住每当我想要运行init代码时运行迁移。拉下生产数据库或类似数据库之类的事情通常会导致问题,因为不会触发迁移。

1 个答案:

答案 0 :(得分:3)

我会建议connection_created信号,即:

  

当数据库包装器进行初始连接时发送   数据库。如果您想发送任何帖子,这将特别有用   连接命令到SQL后端。

因此,当应用程序在应用程序循环开始时连接到数据库时,它将执行信号代码。

它也可以在多个数据库配置中工作,甚至可以在初始化时分离应用程序所做的连接:

  

<强>连接
  已打开的数据库连接。这可以在多数据库配置中使用,以区分连接信号   来自不同的数据库。

注意:
您可能需要考虑使用post_migrateconnection_created信号的组合,同时检查AppConfig.ready()内部是否发生迁移(例如,标记post_migrate信号的激活):

from django.apps import AppConfig
from django.db.models.signals import post_migrate, connection_created
# OR for Django 2.0+
# django.db.backends.signals import post_migrate, connection_created

migration_happened = false

def post_migration_callback(sender, **kwargs):
    ...
    migration_happened = true


def init_my_app(sender, connection):
    ...


class MyAppConfig(AppConfig):
    ...

    def ready(self):
        post_migrate.connect(post_migration_callback, sender=self)

        if !migration_happened:
            connection_created.connect(init_my_app, sender=self)