2012-04-12 2 views
0

전체 코드 블록에 대해 데이터베이스를 변경하는 방법이 있습니까? 예를 들어 : 난 그냥 상황에 따라 서로 다른 DB를 사용할 필요가 모든 시간을() 방법을 사용하여 을 사용하는 아이디어를 좋아하지 않는다전체 코드 블록에 대해 db를 변경하는 방법

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

:

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

의 동등 할 것이다 : \

답변

0

관리자를 사용하고 싶습니다. 당신의 models.py에서 : 기본적 관리자가 단순히 객체

+0

예. 나는 그것에 대해 생각했지만 모든 모델을 사용하여 모든 관리자를 정의해야합니다. – code22

+0

@ code22 관리자는 모델 추상이므로 각 데이터베이스에 하나만 존재합니다. 그러면 관리자를 삽입 할 수 있습니다 당신이 원하는 각 모델에서. – luke14free

+0

하지만 사용자 또는 내가 정의하지 않은 다른 모델의 관리자를 추가 할 수 없습니다. 모델을 수정할 필요가없는 솔루션을 찾고있었습니다. – code22

0

동작은, 일부 글로벌 값을 수정할 필요로 이름을 바꿉니다로 objects_db_one 또는 objects_db_two을 사용하려면

는 또는 IMO, 따라서 with statement은 아니다
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() 

적절한 방법.

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

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(...) 

또한 luke14free의 코드와 같은 목표를 달성 검색어 세트 수준에서 작동하도록 db_manager을 사용할 수 물론,은, 암시 더러운 및 스레드 안전하지 않은 방법으로 수행 할 수 있습니다

Explicit가 암시 적보다 낫다는 것을 기억하십시오. 코드를 정렬하고 동일한 db를 함수 호출에 포함하는 쿼리 세트를 포함하는 것이 더 좋을 것입니다.

+0

스레드 안전은이 문제를 해결할 전역 변수를 배제하는 주된 이유입니다. 한 블록의 코드에서 서로 다른 모델에 최소한 몇 가지 db 작업을 사용해야하므로 이러한 문을 사용하면 코드를 훨씬 읽기 쉽고 간단하게 만들 수 있지만 잘못된 생각 일 수 있습니다. 어쨌든 _using() _을 사용해야 할 것입니다. thx – code22

+0

@ code22 네, 답변에서'db_manager' 부분에서 언급 한 것처럼 중복을 줄이기 위해'using()'을 최상위 레벨에 놓는 것이 낫습니다. – okm

관련 문제