Изменение базы данных для каждого просмотра и доступ к нескольким базам данных для каждого просмотра - PullRequest
4 голосов
/ 13 августа 2011

У меня проблемы с использованием SQLAlchemy в Pyramid. Хотя я могу найти примеры того, что мне нужно, они, как правило, очень короткие и отсутствуют. Так что я закончил с фрагментарным кодом, который едва ли имеет смысл. Поэтому я надеюсь, что кто-нибудь сможет дать более полный пример того, что мне нужно сделать.

У меня есть 4 базы данных с одной и той же схемой. Я хочу иметь возможность работать с ними из одного приложения Pyramid, иногда перечисляя все «заказы» из всех 4 баз данных, иногда просто перечисляя все «заказы» с «site1». Поскольку схемы одинаковы, я также использую те же классы моделей для баз данных.

Я пробовал это как с sqlahelper, так и с простой SQLAlchemy, но безуспешно. Код ниже использует sqlahelper, но я рад использовать все, что работает:

__ __ INIT. Ру

site1_eng = engine_from_config(settings, prefix='site1.')
site2_eng = engine_from_config(settings, prefix='site2.')
site3_eng = engine_from_config(settings, prefix='site3.')

sqlahelper.add_engine(site1_eng, 'site1_eng')
sqlahelper.add_engine(site2_eng, 'site2_eng')

views.py

def site_orders(request):
    site = request.matchdict['site']
    db_eng = sqlahelper.get_engine(("%s_eng" % (site)))
    conn = db_eng.connect()
    dbsession = sqlahelper.get_session()
    dbsession.configure(bind=conn)

    orders = dbsession.query(Order).order_by(Order.cdate.desc())[:100]

    return dict(orders=orders, pagetitle=(site+" Orders"))

Что происходит?

Хорошо, я надеялся, что это переключит базу данных в зависимости от URL, и это так! Тем не менее, это кажется совершенно случайным в отношении того, что выбирает. Так что / orders / site1 / иногда попадает в базу данных site2, а иногда на site3. Обновление часто переключает базу данных, которую она выбирает каждый раз. То же самое для других URL.

Это почти так, как будто сеанс не привязан к базе данных, и его выборка происходит в зависимости от того, что происходит в данный момент в сеансе? Это может не иметь смысла - мое понимание SQLAlchemy не велико.

Действительно надеюсь, что кто-то может помочь, поскольку все зависит от способности быстро и легко переключать базы данных в представлении, и в настоящий момент кажется совершенно невозможным управлять им.

Примечание: Первоначально я попытался следовать и изменить учебник Pyramid SQLA + URL Dispatcher, который использовал:

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))

Но я удалил это при поиске sqlahelper. Если я буду использовать его, дайте мне знать.

Ответы [ 2 ]

8 голосов
/ 13 августа 2011

Настройка и подключение для каждого запроса мне кажется большой работой.Я бы создал четыре обработчика сеансов в моём модуле модели и просто выбрал из них.

Пример:

models/__init__.py

DBSession1 = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))  
DBSession2 = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))  
DBSession3 = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))  
DBSession4 = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))  
metadata1 = MetaData()                                                           
metadata2 = MetaData()                                                           
metadata3 = MetaData()                                                           
metadata4 = MetaData()                                                           

def initialize_sql(engines, drop_db=False):                                      
    DBSession1.configure(bind=engine[0])
    DBSession2.configure(bind=engine[1])                                            
    DBSession3.configure(bind=engine[2])                                            
    DBSession4.configure(bind=engine[3])                                            
    metadata1.bind = engine[0]                                            
    metadata2.bind = engine[1]                                            
    metadata3.bind = engine[2]                                            
    metadata4.bind = engine[3]  

, а затем, на ваш взгляд:

from mypackage.models import DBSession1, DBSession2, DBSession3, DBSession4

def site_orders(request)                                                      
    site = request.matchdict['site']                                                      
    dbsession = globals().get("DBSession%d" % site)                                                      
    orders = dbsession.query(Order).order_by(Order.cdate.desc())[:100]                                                      
    return dict(orders=orders, pagetitle=(site+" Orders"))
1 голос
/ 15 августа 2011

Вы можете установить движок на сеанс sqlalchemy напрямую

Пример для перечисления всех "заказов" из всех 4 баз данных:

def site_orders(request):
    ...
    orders = []
    for engine in engines:
        dbsession.bind = engine
        orders += dbsession.query(Order).order_by(Order.cdate.desc())[:100]

    return dict(orders=orders, pagetitle=(site+" Orders"))
...