在使用Django时,我们很多时候都是与一个数据库打交道,特别是对于小工程来说。不过如果要在同一工程里同时使用多个数据库呢?那也挺简单的,只需几步即可达到该目标。
首先,我们肯定需要在工程配置文件(默认为settings.py)中的DATABASES配置项定义我们要使用的所有数据库。
DATABASES = { 'default': { 'NAME': 'app_data', 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'USER': 'postgres_user', 'PASSWORD': 's3krit' }, 'auth_db': { 'NAME': 'auth_db', 'ENGINE': 'django.db.backends.mysql', 'USER': 'mysql_user', 'PASSWORD': 'swordfish', } }
这里我们定义了两个数据库,其中一个是“default”,这是通常都会存在的配置,因为它代表默认情况。当然如果你确实用不着这个,也可以将其置为一个空字典,如下所示:
DATABASES = { 'default': {}, ... }
那么对于多数据库的使用,最基本的方式是手动指定应该用哪个数据库,如:
>>> # 这会使用默认数据库 >>> Author.objects.all() >>> # 与上面的效果相同 >>> Author.objects.using('default').all() >>> # 指定使用“auth_db”数据库 >>> Author.objects.using('auth_db').all()
以上是针对查询,如果是执行保存,那可以在使用save方法时显示传入using参数:
>>> my_object.save(using='auth_db')
不过如果每次都这样,那岂不是会相当的麻烦。好在Django还为我们提供了另一种更为科学而智能的机制 —— 数据库路由。这不禁让我想到了计算机网络中的路由器,它能将接受到的数据包根据规则分发到指定的端口上去。而这里的数据库路由也扮演了这样的角色。来看一个例子,在之前我们定义了两个数据库“default”和“auth_db”,“default”是默认数据库,而“auth_db”则负责用户相关的数据。于是我们要求对于auth应用中的数据库查询都使用“auth_db”,借助于Router我们可以做如下定义:
class AuthRouter(object): """ A router to control all database operations on models in the auth application. """ def db_for_read(self, model, **hints): """ Attempts to read auth models go to auth_db. """ if model._meta.app_label == 'auth': return 'auth_db' return None def db_for_write(self, model, **hints): """ Attempts to write auth models go to auth_db. """ if model._meta.app_label == 'auth': return 'auth_db' return None def allow_relation(self, obj1, obj2, **hints): """ Allow relations if a model in the auth app is involved. """ if obj1._meta.app_label == 'auth' or \ obj2._meta.app_label == 'auth': return True return None def allow_migrate(self, db, model): """ Make sure the auth app only appears in the 'auth_db' database. """ if db == 'auth_db': return model._meta.app_label == 'auth' elif model._meta.app_label == 'auth': return False return None
一个Router类最多会包含以上这四个方法,分别针对数据库读、写、对象关系和同步,具体可以参考官方文档。
然后我们需要告知Django使用该路由机制,这由一个配置项DATABASE_ROUTERS指定:
DATABASE_ROUTERS = ['path.to.AuthRouter']
这样就OK了!
这里的学问和需要讲究的地方还有很多,要详细了解,可以仔细阅读一下Django官方文档关于这一部分的介绍。