コード ブロック全体のデータベースを変更する方法はありますか。例えば:
with using_db('my_other_db_conf'):
MyModel.objects.all()
これは次と同等です:
MyModel.objects.using('my_other_db_conf').all()
コンテキストに応じて異なる DB を使用する必要があるだけで、毎回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(...)
明示的は暗黙的よりも優れていることに注意してください。コードを配置し、同じデータベースを共有するクエリセットを関数呼び出しに囲むだけでよいでしょう。