django multidb --- router

之前一篇随笔, 提到了django中怎么使用多数据库, 但是在实际工程中遇到了一个问题,就是admin指定了使用某库, 在测试环境上没问题, 当部署后(库也变动了位置), 修改一个admin的model object保存后就报错.

  No such table

追溯了下源码, 没有找到问题,  但可以确定的是那个保存操作并没有使用到我们指定的数据库,使用了default.

最后是使用了django的router解决了这个问题

 

那么django的router是什么?

就是一个类, 定义了如下方法

db_for_read(model, **hints)
db_for_write(model, **hints)
allow_relation(obj1, obj2, **hints)
allow_syncdb(db, model)

 

django router有什么用?

看这个函数名我们就知道了, 我们可以决定一个model在读的时候用哪个db,  db_for_read返回一个settings.DATABASES中的db名或者None

 

比如在写这篇笔记实际经历的项目中, 我们要让一个叫做huodongappcms的app的所有model都读写一个远程数据库(配置为huodongapp), 我们在这个app的models中定义了么一个router

 1 class HuodongappcmsRouter(object):
 2     """
 3     A router to control all database operations on models in the
 4     this app.
 5     """
 6     def db_for_read(self, model, **hints):
 7        """
 8         Attempts to read auth models go to auth_db.
 9        """
10         if model._meta.app_label == 'huodongappcms':     #model所属的app
11             return 'huodongapp'
12         return None
13 
14     def db_for_write(self, model, **hints):
15         """
16         Attempts to write auth models go to auth_db.
17         """
18         if model._meta.app_label == 'huodongappcms':
19             return 'huodongapp'
20         return None

 

然后加入settings中的DATABASE_ROUTERS, 使用Router的全路径, django会根据DATABASE_ROUTERS中router指定的顺序依次调用.

DATABASE_ROUTERS = ['huodongappcms.models.HuodongappRouter']

 当我添加了如上的Router后 ,我去掉了huodongapp中admin对多数据库的想关定制, 一样是work的

 

 

2. 如果我们还想让这个app以外的其它app写都写到一个主库master中, 读都随机的从两个从库slave1, slave2之一读, 那么写这样一个Router

class MasterSlaveRouter(object):
    def db_for_read(self, model, **hint):
        import random
        return random.choice(['slave1', 'slave2'])

    def db_for_write(self, model, **hint):
        return 'master'

 

然后加入到DATABASE_ROUTERS中

 

 

3, 稍微追溯一下源码, 当需要一个db时, 拿数据库的manager举例, 会通过django.db的router去获取

而router就是django.db.utils中定义的一个类, 它使用了DATABASE_ROUTERS配置. 

下面是Manager的db方法.

from django.db import router
class Manager():
    @property
    def db(self):          
        return self._db or router.db_for_read(self.model)

 

 

这里只讨论了django Router的db_for_read和db_for_write

和ForeignKey相关西的allow_relation以及用于数据库同步的allow_sync以后讨论

 

 

参考:

https://docs.djangoproject.com/en/1.6/topics/db/multi-db/#automatic-database-routing

posted on 2014-06-18 11:59  小宇2  阅读(3033)  评论(2编辑  收藏  举报

导航