Django:在每次启动时都在运行代码,但在迁移数据库之后 [英] Django: running code on every startup but after database is migrated

查看:270
本文介绍了Django:在每次启动时都在运行代码,但在迁移数据库之后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I thought there was an easy answer to this in recent versions of Django but I can't find it.

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

I have code that touches the database. I want it to run every time Django starts up. I seem to have two options:

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

Option 1. AppConfig.ready() - this works but also runs before database tables have been created (i.e. during tests or when reinitializing the app without data). If I use this I have to catch multiple types of Exceptions and guess that the cause is an empty 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)-但这仅在以下情况下运行我进行了迁移。

Option 2. Use post_migrate.connect(foo_init, sender=self) - but this only runs when I do a migration.

选项3。旧方法-从 urls.py -我想将这样的东西排除在 urls.py 之外,我认为 AppConfig 是唯一的选择路径

Option 3. The old way - call it from urls.py - I wanted to keep stuff like this out of urls.py and I thought AppConfig was the one true path

到目前为止,我已经选择了解决方案2-我不喜欢臭臭的尝试/ except选项1和选项3中的内容使我烦恼,因为 urls.py 变成了垃圾场。

I've settled for option 2 so far - I don't like the smelly try/except stuff in Option 1 and Option 3 bugs me as urls.py becomes a dumping ground.

但是,选项当我在本地开发时,2经常使我绊倒-我需要记住每当我要运行初始化代码时就运行迁移。诸如关闭生产数据库之类的操作通常会引起问题,因为未触发迁移。

However Option 2 often trips me up when I'm developing locally - I need to remember to run migrations whenever I want my init code to run. Things like pulling down a production db or similar often cause problems because migrations aren't triggered.

推荐答案

我建议 connection_created 信号,即:

I would suggest the connection_created signal, which is:


在数据库包装程序与
数据库建立初始连接时发送。如果您想将任何后
连接命令发送到SQL后端,这将特别有用。

Sent when the database wrapper makes the initial connection to the database. This is particularly useful if you’d like to send any post connection commands to the SQL backend.

因此当应用程序在应用程序周期开始时连接到数据库时,执行信号的代码。

So it will execute the signal's code when the app connects to the database at the start of the application's cycle.

它还可以在多个数据库配置中工作,甚至可以分开由初始化时的应用程序:

It will also work within a multiple database configuration and even separate the connections made by the app at initialization:


连接

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

connection
The database connection that was opened. This can be used in a multiple-database configuration to differentiate connection signals from different databases.






注意:

您可能要考虑结合使用 post_migrate connection_created 信号同时检查您的 AppConfig.ready()是否发生了迁移(例如,标记 post_migrate 信号的激活) :


Note:
You may want to consider using a combination of post_migrate and connection_created signals while checking inside your AppConfig.ready() if a migration happened (ex. flag the activation of a post_migrate signal):

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)

这篇关于Django:在每次启动时都在运行代码,但在迁移数据库之后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆