ficapy
5/13/2015 - 8:25 AM

Sqlalchemy use scoped_session in Tornado

Sqlalchemy use scoped_session in Tornado

# -*- coding: utf-8 -*-

import threading

class Metaclass(type):
    # property() doesn't work on classmethods,
    #  see http://stackoverflow.com/q/128573/1231454

    @property
    def data(cls):
        if not hasattr(cls._state, 'data'):
            return {}
        return cls._state.data

class ThreadRequestContext(object, metaclass=Metaclass):

    """A context manager that saves some per-thread state globally.
    Intended for use with Tornado's StackContext.

    Provide arbitrary data as kwargs upon creation,
    then use ThreadRequestContext.data to access it.
    """

    _state = threading.local()
    _state.data = {}


    def __init__(self, **data):
        self._data = data

    def __enter__(self):
        self._prev_data = self.__class__.data
        self.__class__._state.data = self._data

    def __exit__(self, *exc):
        self.__class__._state.data = self._prev_data
        del self._prev_data
        return False

def get_current_request_id():
    return ThreadRequestContext.data['request_id']
# -*- coding: utf-8 -*-

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base

from config import Config
from tools.tor import get_current_request_id


engine = create_engine(Config.DB,
                       encoding='utf-8',
                       echo=Config.SQLALCHEMY_ECHO,
                       pool_recycle=600,
                       pool_size=20,
                       max_overflow=100)

db = scoped_session(sessionmaker(bind=engine,
                                 autocommit=False,
                                 autoflush=True,
                                 expire_on_commit=False,
                                 ), scopefunc=get_current_request_id)


Base = declarative_base()
# -*- coding: utf-8 -*-

from sqlalchemy import Column
from sqlalchemy.dialects.mysql import INTEGER, BIT, VARCHAR

from store import Base
from store import db

class User(Base):

    __tablename__ = "user"

    id = Column(INTEGER, primary_key=True, autoincrement=True)
    username = Column(VARCHAR(20), nullable=False)
    password = Column(VARCHAR(20), nullable=False)
    is_delete = Column(BIT, default=0, nullable=False)

    @classmethod
    def get_all(cls):
        return db.query(User).filter(User.is_delete == 0).all()
# -*- coding: utf-8 -*-

import store
from tools.tor import ThreadRequestContext


class BaseHandler(RequestHandler):

    def prepare(self):
        store.db()

    def on_finish(self):
        store.db.remove()

    def _execute(self, transforms, *args, **kwargs):
        global_data = {"request_id": id(self)}
        with stack_context.StackContext(functools.partial(ThreadRequestContext, **global_data)):
            return super(BaseHandler, self)._execute(transforms, *args, **kwargs)