Django 数据库路由器

Django DB Routers

我的 Django 应用程序将为 3 个不同的应用程序(产品、制造商、基金)连接 3 个不同的数据库(默认为 SQLite,用于产品和制造商数据库的 PostgreSQL,用于基金数据库的 MSSQL)

我在每个应用程序的 routers.py (productdbrouter, manufacturerdbrouter, fundsdbrouter) 文件中创建了 3 个路由器,以根据 app_lable名字。

在我的项目设置文件中,我创建了一个 DATABASE_ROUTERS 配置为:

DATABASE_ROUTERS = [
    "product.routers.productdbrouter","manufacturer.routers.manufacturerdbrouter", "funds.routers.fundsdbrouter",
]

现在,当我尝试访问应用程序时,它总是尝试从数据库配置中的第一个路由器中找到 table(在本例中为 product.routers.productdbrouter),如果 table丢失然后它尝试从默认路由器(SQLite)获取。 我期望路由器根据我尝试获取的模型映射到 products/manufacturer/Funds 数据库。

非常感谢关于我在配置上缺少什么的建议?

顺便说一下,我使用的是 Django=2.2.4

代码

products\router.py

class productdbrouter(object):
    def db_for_read(self, model, **hints):    
        if model._meta.app_label== 'product':
            return 'productdb'
        return 'default'

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'product':
            return 'productdb'
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'product' and obj2._meta.app_label == 'product':
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label=='product':
            return db=='productdb'
        return 'default'

    def allow_syncdb(self, db, model):
        if db == 'productdb' or model._meta.app_label == "product":
            return False  # we're not using syncdb on our legacy database
        else:  # but all other models/databases are fine
            return True

manufacturer\router.py

class manufacturerdbrouter(object):
    def db_for_read(self, model, **hints):    
        if model._meta.app_label== 'manufacturer':
            return 'manufacturerdb'
        return 'default'

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'manufacturer':
            return 'manufacturerdb'
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'manufacturer' and obj2._meta.app_label == 'manufacturer':
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label=='manufacturer':
            return db=='manufacturerdb'
        return 'default'

    def allow_syncdb(self, db, model):
        if db == 'manufacturerdb' or model._meta.app_label == "manufacturer":
            return False  # we're not using syncdb on our legacy database
        else:  # but all other models/databases are fine
            return True

funds\router.py

class fundsdbrouter(object):
    def db_for_read(self, model, **hints):    
        if model._meta.app_label== 'funds':
            return 'fundsdb'
        return 'default'

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'funds':
            return 'fundsdb'
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'funds' and obj2._meta.app_label == 'funds':
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label=='funds':
            return db=='fundsdb'
        return 'default'

    def allow_syncdb(self, db, model):
        if db == 'fundsdb' or model._meta.app_label == "funds":
            return False  # we're not using syncdb on our legacy database
        else:  # but all other models/databases are fine
            return True

注意:我设置了 allow_syncdb =false,因为我没有从 django 应用程序中推送任何值。在应用程序中所做的所有更改将通过其他应用程序进行。

感谢帮助

我认为问题在于您使用代码 return 'default' 而不是使用 return None 返回建议。请参阅此处的文档:

https://docs.djangoproject.com/en/2.2/topics/db/multi-db/#database-routers

您也可以在整个项目中使用单个路由器,就像这样:

class MyRouter(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'product':
            return 'productdb'
        elif model._meta.app_label == 'manufacturer':
            return 'manufacturerdb'

        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'product':
            return 'productdb'
        elif model._meta.app_label == 'manufacturer':
            return 'manufacturerdb'

        return None

    def allow_relation(self, obj1, obj2, **hints):
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if db in (
                'productdb',
                'manufacturerdb',
        ):
            return False

        return True

我们正在做的是将您创建的每个 Django 应用程序的读写路由到适当的数据库(如 Django 设置中 DATABASES 中所定义),或返回 None,这将在您的设置中使用默认的 SQLite 数据库。我们还告诉 Django 不要创建任何针对 PostgreSQL 或 MSSQL 的迁移,因为我猜你不会想让 Django 处理这些数据库的结构。

不过,我们这里不考虑allow_relation;是否设置任何跨数据库边界的关系取决于您。例如,您无法设置从 SQLite 到 PostgreSQL 的 ForeignKey。祝你好运!