Django - 多个数据库 - 如何定义路由器?

时间:2018-01-24 16:16:38

标签: python django django-models

我想将我的应用程序连接到3个不同的数据库。

为此,我在设置文件中更改了以下代码:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'local_db',
        'USER': 'root',
        'PASSWORD': 'password1',
        'HOST': 'localhost',
        'PORT': '3306',
        'OPTIONS': { 'sql_mode': 'traditional', }
    },
    'firstExternalDb': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'firstExternalDb',
        'USER': 'userName',
        'PASSWORD': 'password1',
        'HOST': 'firstExternalDb.node.com',
        'PORT': '3306',
        'OPTIONS': { 'sql_mode': 'traditional', }
    },
    'secondExternalDb': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'secondExternalDb',
        'USER': 'userName',
        'PASSWORD': 'password1',
        'HOST': 'secondExternalDb.node.com',
        'PORT': '3306',
        'OPTIONS': { 'sql_mode': 'traditional', }
    },
}

我想有可能指定我将创建数据表的数据库。例如所有django表,如'auth_group','django_admin_log',我想保存在localhost中。

正在尝试创建一个完成本教程https://docs.djangoproject.com/pl/1.11/topics/db/multi-db/#topics-db-multi-db-routing

的路由器

但我不明白这一点。你能否回答我的问题:

  • 我应该为每个应用程序创建新的路由器吗?
  • 如何定义默认数据库应该使用所有django表?

我在两个模型文件中创建了两个路由器: 第一个仅用于默认DB:

class defaultRouter:
    def db_for_read(self, model, **hints): 
        return 'default'

    def db_for_write(self, model, **hints): 
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        db_list = ('default')
        if obj1._state.db in db_list and obj2._state.db in db_list: 
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints): 
        return True

第二个应用程序内的第二个:

class secondExternalDbRouter:
    def db_for_read(self, model, **hints): 
        return 'secondExternalDb'

    def db_for_write(self, model, **hints): 
        return 'secondExternalDb'

    def allow_relation(self, obj1, obj2, **hints):
        db_list = ('secondExternalDb')
        if obj1._state.db in db_list and obj2._state.db in db_list: 
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints): 
        return True

两个路由器都在模型类的正下方,在同一个文件中。

设置文件:

  

DATABASE_ROUTERS =   [ 'mainApp.models.defaultRouter', 'secondApp.models.secondExternalDbRouter',]

2 个答案:

答案 0 :(得分:0)

您不必为每个应用程序创建新的路由器。如果使代码更加模块化,你可能想要这样做,即你可以将路由器与其他代码保持在一起,但我个人最初不会这样做。

如果您没有为表指定读取或写入映射,则将使用默认数据库。换句话说,您只需要为不使用默认数据库的任何案例创建路由逻辑。例如,这会强制表只读,但不会影响其他任何内容:

class MyCustomRouter(object):
    def db_for_write(self, model, **hints):
        if model == MyReadOnlyModel:
            raise Exception("This model is read only. Shame!")
        return None

有关更多示例,请参阅 Django - how to specify a database for a model?

答案 1 :(得分:0)

默认路由器

class DefaultDBRouter(object):
    """
    A router to control all database operations on models in the
    auth application.
    """

    def db_for_read(self, model, **hints):
        """
        Reads go to a default.
        """
        return "default"

    def db_for_write(self, model, **hints):
        """
        Writes always go to default.
        """
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the default.
        """
        db_list = ('default')
        if obj1._state.db in db_list and obj2._state.db in db_list:
            return True
        return None

    def allow_migrate(self, db, app_label, model=None, **hints):
        """
        All non-micro-management models end up in this pool.
        """
        return True

<强> FirstExternalDBRouter

FIRST_EXTERNAL_APPS = [
    # DEFINE APPS TO USE THIS DB
]


class FirstExternalDBRouter(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label in FIRST_EXTERNAL_APPS:
            return 'firstExternalDb'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in FIRST_EXTERNAL_APPS:
            return 'firstExternalDb'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label in FIRST_EXTERNAL_APPS or \
                obj2._meta.app_label in FIRST_EXTERNAL_APPS:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in FIRST_EXTERNAL_APPS:
            return db == 'firstExternalDb'
        return None

<强> SecondExternalDBRouter

SECOND_EXTERNAL_APPS = [
    # DEFINE APPS TO USE THIS DB
]


class SecondExternalDBRouter(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label in SECOND_EXTERNAL_APPS:
            return 'secondExternalDb'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in SECOND_EXTERNAL_APPS:
            return 'secondExternalDb'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label in SECOND_EXTERNAL_APPS or \
                obj2._meta.app_label in SECOND_EXTERNAL_APPS:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in SECOND_EXTERNAL_APPS:
            return db == 'secondExternalDb'
        return None

在参数 DATABASE_ROUTERS

中的设置中定义所有三个路由器

所有三个数据库都将具有相同的模式迁移(表),只有您将控制在访问模型时要读取和写入的数据库。