【问题标题】:Django - multiple databases - how to define the router?Django - 多个数据库 - 如何定义路由器?
【发布时间】:2018-07-03 18:24:26
【问题描述】:

我想将我的应用程序连接到 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', }
    },
}

我希望能够指定我将为哪个数据库创建数据表。例如我想保存在 localhost 中的所有 django 表,如 'auth_group' 、 'django_admin_log'。

正在尝试通过本教程创建路由器https://docs.djangoproject.com/pl/1.11/topics/db/multi-db/#topics-db-multi-db-routing

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

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

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

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',]

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

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

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

    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?

    【讨论】:

      【解决方案2】:

      默认路由器

      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

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

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

      【讨论】:

      • 感谢您的代码。我改变了一切,但如果我运行命令:“python2.7 manage.py migrate --database=secondExternalDb”
      • 程序在 secondExternalDb 数据库中创建所有 django 数据表
      • 你知道为什么吗?
      • 当维护多个数据库时,您应该确保所有数据库具有相同的模式(表)。表将相同,但数据会保留在您指定的数据库中。
      猜你喜欢
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      • 2014-08-09
      • 2017-06-16
      • 2016-10-26
      • 1970-01-01
      相关资源
      最近更新 更多