有没有办法为整个代码块更改数据库。例如:
with using_db('my_other_db_conf'):
MyModel.objects.all()
这相当于:
MyModel.objects.using('my_other_db_conf').all()
我只需要根据上下文使用不同的数据库,并且不喜欢每次都使用using()方法的想法:\
我会使用经理。在你的 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 作为默认管理器,只需将其重命名为 objects
行为需要修改一些全局值,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 比 implicit 更好,只需安排您的代码并将共享相同数据库的查询集附在函数调用中,会更好。