Django数据库路由器

时间:2019-09-14 17:33:10

标签: django router

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

我在每个应用程序的routers.pyproductdbroutermanufacturerdbrouterfundsdbrouter)文件中创建了3个路由器,以根据app_lable名称执行读取,写入操作。

在我的项目设置文件中,我创建了DATABASE_ROUTERS配置,如下:

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

现在,当我尝试访问应用程序时,它总是尝试从数据库配置中的第一个路由器查找表(在这种情况下为product.routers.productdbrouter),如果该表丢失了,它将尝试从默认值中获取路由器(SQLite)。 我期望的是路由器,它映射到产品/制造商/基金数据库,具体取决于我尝试获取的模型。

高度推荐有关配置中缺少Iam的建议?

顺便说一句,我使用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

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

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

我认为问题在于您返回的建议是代码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。祝你好运!