如何更改整个代码块的db

时间:2012-04-12 07:20:02

标签: python django

有没有办法为整个代码块更改数据库。例如:

with using_db('my_other_db_conf'):
    MyModel.objects.all()

相当于:

MyModel.objects.using('my_other_db_conf').all()

我只需要根据上下文使用不同的数据库,并且不喜欢每次使用 using()方法的想法:\

2 个答案:

答案 0 :(得分:0)

我会使用经理。在models.py中:

class DB_one_ItemsManager(models.Manager):
    def get_query_set(self):
        return super(DB_one_ItemsManager, self).get_query_set().using("database1")

class DB_two_ItemsManager(models.Manager):
    def get_query_set(self):
        return super(DB_two_ItemsManager, self).get_query_set().using("database2")

class YourModel(models.Model):    
    #Some fields here
    #...

    objects_db_one=DB_one_ItemsManager()
    objects_db_two=DB_two_ItemsManager()

或者,如果您想使用objects_db_one或objects_db_two作为默认管理器,只需将其重命名为对象

答案 1 :(得分:0)

行为需要修改一些全局值IMO,因此with statement不是合适的方式。当然,它可以以隐式,脏和线程不安全的方式完成:

from contextlib import contextmanager 
@contextmanager 
def unsafe_modify_queryset_db(model_dbs): 
    """model_dbs => sequence of tuple (model, db for the model to use).

    For example ((User, 'slice_2'), ...) 
    """ 
    prev_db = map(lambda x:x[0].objects._db , model_dbs) 
    for model, db in model_dbs: 
        model.objects._db = db 
    yield 
    # restore previous db 
    for x, db in zip(model_dbs, prev_db): 
        x[0].objects._db = prev_db 

# then
with unsafe_modify_queryset_db((User, 'slice_2', ...)):
    User.objects.filter(...)

你也可以使用db_manager来操作QuerySet级别,这与luke14free的代码达到了相同的目标:

qs = User.objects.db_manager('slice_2')
foo = qs.filter(...)
bar = qs.filter(...)

请记住, Explicit比隐式更好,只需安排你的代码并将共享相同db的查询集包含在函数调用中,就会更好。

相关问题