用于 django 中迁移的自动数据库路由器

Automatic db router for migrations in django

我正在构建一个由 Django 支持的站点,我想为一些应用程序创建单独的数据库,我构建了一个灵活的路由器,将每个应用程序路由到预定义的数据库,这很好用。 问题是,当我迁移我的模型时,我每次都必须设置 --database 参数,我发现这很烦人而且多余。还有很多次,我用迁移后的应用程序中的表淹没了我的默认数据库(忘记添加 --database)。 我在我的路由器中试验了 allow_migrate(...) 功能,但我所能实现的只是安全机制,如果我忘记指定数据库,则不会 运行 迁移。 我的问题是:有没有办法在 Django 中为模型迁移设置自动数据库选择? 我的方法可能是错误的,令我惊讶的是以前似乎没有人这样做过。

我不知道有什么方法可以自动执行此操作。但是,一个简单的方法可能是 migrate 命令的 write your own version,它使用适当的 --database 和应用程序参数多次调用 Django migrate 命令。

根据 Django 迁移的作者,这是 a conscious design decision,所以我不希望它发生变化:"Just like syncdb, migrate only runs on one database at a time, so you must execute it individually for each database, as you suggest. This is by design."

对于遇到我遇到的问题的任何人,这是我最终确定的:

routers.py:

from django.conf import settings
class DatabaseAppsRouter(object):

    def db_for_read(self, model, **hints):
        #  your db routing

    def db_for_write(self, model, **hints):
        #  your db routing

    def allow_relation(self, obj1, obj2, **hints):
        #  your db routing

    def allow_syncdb(self, db, model):
        #  your db routing

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if db in settings.DATABASE_APPS_MAPPING.values():
            return settings.DATABASE_APPS_MAPPING.get(app_label) == db
        elif app_label in settings.DATABASE_APPS_MAPPING:
            return False

settings.py

DATABASE_ROUTERS = ['project.routers.DatabaseAppsRouter']
DATABASE_APPS_MAPPING = {'contenttypes': 'default',
                     'auth': 'default',
                     'admin': 'default',
                     'sessions': 'default',
                     'messages': 'default',
                     'staticfiles': 'default',
                     'myapp': 'mydb',
                     }

此设置让我可以 运行 两个命令:

python manage.py migrate
python manage.py migrate --database=mydb

这仍然是一对多,但至少现在我不能错误地将我的应用程序迁移到我想承认的发生了更多次的默认数据库。


警告 - 咆哮:

到目前为止,我发现 Django 的设计很古怪,但非常合乎逻辑且对程序员友好,就像 python 本身一样。但是迁移与多个数据库设置交互的方式确实很不方便,很容易让你的默认数据库充满不需要的表。 凯文在他的回答中链接的讨论表明,我不是唯一遇到这种困难的人。