BLOG
Enjoy when you can, and endure when you must.
MAR 19, 2014/Django
Django多数据库的简单应用

在使用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官方文档关于这一部分的介绍。

COMMENTS
LEAVE COMMNT