2011-12-30 10 views
6

Kasırga kullanarak, SQLAlchemy oturumlarımın düzgün bir şekilde kapatılıp temizlenmesini ve böylece nesnelerin bir istekten diğerine paylaşılmamasını sağlamak için biraz ara yazılım büyüsü oluşturmak istiyorum. İşin sırrı, bazı kasırga işleyicilerim eşzamansız olduğundan, her istek için yalnızca bir oturum paylaşamıyorum.SQLAlchemy + Tornado: SQLAlchemy's ScopedSession için scopefunc nasıl oluşturulur?

Her istek için nasıl yeni bir oturum oluşturulacağını bilen bir Kapsamlı Oturum oluşturmaya çalışıyorum. Tek yapmam gereken, şu anda yürütme isteğini bir tür benzersiz anahtar haline dönüştürebilen kodum için bir scopefunc tanımlamaktır, ancak şu andaki isteği herhangi bir noktada 'a nasıl aldığımı anlayamıyorum (işlevimin her ikisine de erişemediği geçerli RequestHandler kapsamı dışında).

Bu işi yapmak için yapabileceğim bir şey var mı?

+2

Hiç bir kasırga tanımıyorum ama Session'ı isteğin kendisi ile ilişkilendirmek isteyebilirsiniz (yani, uygun değilse scopedsession kullanmayın). o zaman sadece request.session deyin. Kurulum/açma için başlangıçta/sonunda kancalara sahip olması gerekir. – zzzeek

+0

@zzzeek Eğer bunu cevap olarak gönderirseniz, doğru olarak işaretleyeceğim! Bunu düşündüğümde, hak ettiğimi daha çok anladım - ihtiyacım olan şeyi elde etmenin en hızlı ve en kolay yolu bu. Teşekkürler! –

+0

Aynı düşünmekteyim, tüm async işleyicileri arasında tutarsızlık yaratacak bir oturumun paylaşılması tutarsızlık yaratacaktır, değil mi? Bir işleyicide, işleyicinin sonunda scopped_session.remove() öğesini çağırabilirim ancak diğer işleyici (zaman uyumsuz olarak çalışıyor) yine de kullanıyor olabilir! – giga

cevap

4

Session isteği ile ilişkilendirmek isteyebilirsiniz (yani, uygun değilse scopedsession kullanmayın). O zaman sadece request.session deyin. Kurulum/yıpranma için başlangıç ​​/ bitişte kancalar hala olmalıdır.

düzenleme: Özel kapsam fonksiyonu

def get_current_tornado_request(): 
    # TODO: ask on the Tornado mailing list how 
    # to acquire the request currently being invoked 

Session = scoped_session(sessionmaker(), scopefunc=get_current_tornado_request) 
+0

Temel olarak, yapmam gereken şey, bir isteğin başlangıcında bir oturum oluşturmak ve bunu İstek işleyicisine atamak. ama oturumda ihtiyaç duyulan birçok yöntemi çağırmam gerekiyor, ya istek işleyicisini ya da aralarında oturumu kendim geçmeliyim ... çirkin olmanın kodu :( – giga

+0

daha sonra özel bir kapsam belirleme işleviyle bir scopedsession kullan. – zzzeek

+0

Daha fazlasını açıklayabilir misiniz özel bir kapsam belirleme işlevi nasıl yazabilirim ... teşekkürler. Python – giga

0

(Bu 2011 soruya 2017 cevaptır) @Stefano Borini belirttiği gibi, Tornado 4'te kolay yolu sadece RequestHandler örtülü pass the session around izin vermektir. eşyordam dekoratör kalıplarını kullanırken Tornado işleyicisi örneği durumunu izler: Gerçekten gerçekten uyumsuz bunu beri bir anti-desen ele alacak bir declarative_base (iç SQL Simya oturumu başvurmak gerekiyorsa

import logging 

_logger = logging.getLogger(__name__) 

from sqlalchemy import create_engine, exc as sqla_exc 
from sqlalchemy.orm import sessionmaker, exc as orm_exc 

from tornado import gen 
from tornado.web import RequestHandler 

from my_models import SQLA_Class 

Session = sessionmaker(bind=create_engine(...)) 

class BaseHandler(RequestHandler): 

    @gen.coroutine 
    def prepare(): 
     self.db_session = Session() 

    def on_finish(): 
     self.db_session.close() 

class MyHander(BaseHandler): 

    @gen.coroutine 
    def post(): 
     SQLA_Object = self.db_session.query(SQLA_Class)... 
     SQLA_Object.attribute = ... 

     try: 
      db_session.commit() 
     except sqla_exc.SQLAlchemyError: 
      _logger.exception("Couldn't commit") 
      db_session.rollback() 

aşırı çiftler Uygulamaya model), Amit Matani olmayan bir çalışma örneği var here.