新博客地址:http://gorthon.sinaapp.com/
使用SQLAlchemy+webpy的时候出现了一些问题,记录以备后用。
环境:
>>> web.__version__ '0.36' >>> sqlalchemy.__version__ '0.7.6' >>> MySQLdb.__version__ '1.2.3c1' >>>
1. sqlalchemy与webpy的结合看webpy的cookbook就可以了-- 这里
2. 当启用webpy的session功能后,问题来了,因为webpy提供的是DiskStore、DBStore,他们的使用方法cookbook里面有,猛击这里。
如果不用sqlalchemy而是使用DBStore的话有些注意的地方,连接mysql如下:
# 使用webpy自带数据库api db = web.database( dbn='mysql', db="db_name", user="root", pw="123456", host="127.0.0.1", port=3306, )
# webpy session web.config.session_parameters = web.utils.storage({ 'cookie_name': 'session_id', 'cookie_domain': None, 'cookie_path' : None, 'timeout': 86400, #24 * 60 * 60, # 24 hours in seconds 'ignore_expiry': True, 'ignore_change_ip': True, 'secret_key': 'fLjUfxqXtfNoIldA0A0J', 'expired_message': 'Session expired', 'httponly': True, 'secure': False }) # webpy cookbook和api文档里面都没有提到,可以看webpy的源码来进行设置
调试模式下使用session:
app = web.application(urls, globals()) if web.config.get('_session') is None: session = web.session.Session(app, web.session.DBStore(db, 'sessions')) web.config._session = session else: session = web.config._session
class Store: """Base class for session stores""" def __contains__(self, key): raise NotImplementedError def __getitem__(self, key): raise NotImplementedError def __setitem__(self, key, value): raise NotImplementedError def cleanup(self, timeout): """removes all the expired sessions""" raise NotImplementedError
下面开始构造:
4. 创建session数据库(models.py):
# coding: utf-8 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, CHAR, Text, TIMESTAMP, func from sqlalchemy.orm import sessionmaker, scoped_session mysql_engine = create_engine( 'mysql://%s:%s@%s:%s/app_gorthon?charset=utf8' % ("root", "123456", "127.0.0.1", 3306), encoding='utf8', echo=True ) sql_session = scoped_session(sessionmaker(bind=mysql_engine)) def loadSqla(handler): try: return handler() except web.HTTPError: sql_session.commit() raise except Exception: sql_session.rollback() raise finally: sql_session.commit() Base = declarative_base() class WebpySession(Base): __tablename__ = 'sessions' session_id = Column(CHAR(128), nullable=False, primary_key=True) atime = Column(TIMESTAMP, nullable=False, default=func.current_timestamp()) data = Column(Text, nullable=True) webpy_table = WebpySession.__table__ metadata = Base.metadata if __name__ =='__main__': metadata.create_all(mysql_engine)
先python models.py创建数据库。
5. 接口(utils.py),代码来自group,做了一点修改(第31行加了commit()),其实可以改成用sqlalchemy的session来做,下面这个代码用的是元数据操作的:
#!/usr/bin/python #-*- coding: utf-8 -*- import datetime import web from models import sql_session class SQLAStore(web.session.Store): def __init__(self, table): self.table = table def __contains__(self, key): return bool(sql_session.execute(self.table.select(self.table.c.session_id==key)).fetchone()) def __getitem__(self, key): s = sql_session.execute(self.table.select(self.table.c.session_id==key)).fetchone() if s is None: raise KeyError else: sql_session.execute(self.table.update().values(atime=datetime.datetime.now()).where(self.table.c.session_id==key)) return self.decode(s[self.table.c.data]) def __setitem__(self, key, value): pickled = self.encode(value) if key in self: sql_session.execute(self.table.update().values(data=pickled).where(self.table.c.session_id==key)) else: sql_session.execute(self.table.insert().values(session_id=key, data=pickled)) sql_session.commit() def __delitem__(self, key): sql_session.execute(self.table.delete(self.table.c.session_id==key)) def cleanup(self, timeout): timeout = datetime.timedelta(timeout/(24.0*60*60)) last_allowed_time = datetime.datetime.now() - timeout sql_session.execute(self.table.delete(self.table.c.atime<last_allowed_time))
6. 主文件(请自行import缺少的模块):
app = web.application(urls, globals()) if web.config.get('_session') is None: session = web.session.Session(app, SQLAStore(webpy_table)) web.config._session = session else: session = web.config._session app.add_processor(loadSqla) application = sae.create_wsgi_app(app.wsgifunc())