Django 多数据库

Jun 11, 2015


最近发现手头Django项目比较乱,一个单独的数据库貌似已经无法满足需求了,就研究下Django多数据库的配置和操作,自己试了试果然行得通!具体配置要点如下。


配置数据库

  • 在settings中进行配置。

DATABASES = {
    #之所以这里仍然保留default数据库,是因为如果要使用Django的Auth应用或者Admin应用
    #我希望它默认将数据存放在default.db中,而不与其他数据搞混
     'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db/default.db',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
    },

    #提供给userApp使用
     'userdb': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db/user.db',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
    },

     'essaydb': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db/essay.db',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
    },
}

配置class

  • 新建dbsettings.py , 编写下面 , class一般只改最后一个方法

class appdb(object):
    def db_for_read(self, model, **hints):
        #该方法定义读取时从哪一个数据库读取
        return self.__app_router(model)

    def db_for_write(self, model, **hints):
        #该方法定义写入时从哪一个数据库读取,如果读写分离,可再额外配置
        return self.__app_router(model)

    def allow_relation(self, obj1, obj2, **hints):
        #该方法用于判断传入的obj1和obj2是否允许关联,可用于多对多以及外键
        #同一个应用同一个数据库
        if obj1._meta.app_label == obj2._meta.app_label:
            return True
        #User和Essay是允许关联的
        elif obj1._meta.app_label in ('userApp','essayApp') and obj2._meta.app_label in ('userApp','essayApp'):
            return True

    def allow_syncdb(self, db, model):
        #该方法定义数据库是否能和名为db的数据库同步
        return self.__app_router(model) == db

   #添加一个私有方法用来判断模型属于哪个应用,并返回应该使用的数据库
    def __app_router(self, model):
        if model._meta.app_label == 'userApp':
            return 'userdb'
        elif model._meta.app_label == 'essayApp':
            return 'essaydb'
        else :
            return 'default'

将数据库class添加至settings

  • DATABASE_ROUTERS = [‘dbsettings.appdb’]

同步数据库

  • 使用下列方法分别同步不同数据库:

python manage.py syncdb #默认同步的数据库为'default'
python manage.py syncdb --database=userdb  #为userdb同步数据
python manage.py syncdb --database=essaydb #为essaydb同步数据
  • 反向同步数据库

python manage.py inspectdb --database=userdb > shanyjuser/models.py
  • 注意database=后面是settings里的名字

model的class meta

  • 每个model的class meta 中 app_label = ‘myapp’ 应和(2)中的最后一个方法相匹配!

使用底层sql

  • 除了自带的model之外还可以使用底层sql

    • 针对单数据库
      
      from django.db import connection, transaction
          cursor = connection.cursor()
          # 数据修改操作——提交要求
          cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
          transaction.commit_unless_managed()
          # 或者 transaction.set_dirty()
          # 数据检索操作,不需要提交
          cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
          row = cursor.fetchone()
          return row
      
    • 针对多数据库
      
      from django.db import connections
      cursor = connections['my_db_alias'].cursor()
      cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
      transaction.commit_unless_managed(using='my_db_alias')