我认为在最近的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代码时运行迁移。拉下生产数据库或类似数据库之类的事情通常会导致问题,因为不会触发迁移。
答案 0 :(得分:3)
我会建议connection_created
信号,即:
当数据库包装器进行初始连接时发送 数据库。如果您想发送任何帖子,这将特别有用 连接命令到SQL后端。
因此,当应用程序在应用程序循环开始时连接到数据库时,它将执行信号代码。
它也可以在多个数据库配置中工作,甚至可以在初始化时分离应用程序所做的连接:
<强>连接强>
已打开的数据库连接。这可以在多数据库配置中使用,以区分连接信号 来自不同的数据库。
注意:强>
您可能需要考虑使用post_migrate
和connection_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)