WSGI学习系列Pecan
Pecan Introduce
Pecan是一个轻量级的基于Python的Web框架,
Pecan的目标并不是要成为一个“full stack”的框架,
因此Pecan本身不支持类似Session和Databases.
Pecan Features
(1) Object-dispatch for easy routing
(2) Full support for REST-style controllers
除了上述功能外,还包括以下扩展功能:
Extensible security framework
Extensible template language support
Extensible JSON support
Easy Python-based configuration
Pecan Web Application Files Structure
├── MANIFEST.in ├── config.py ├── public │ ├── css │ │ └── style.css │ └── images ├── setup.cfg ├── setup.py └── test_project ├── __init__.py ├── app.py ├── controllers │ ├── __init__.py │ └── root.py ├── model │ └── __init__.py ├── templates │ ├── error.html │ ├── index.html │ └── layout.html └── tests ├── __init__.py ├── config.py ├── test_functional.py └── test_units.py
以上是一个默认的Pecan Web应用文件包结构。
(1) config.py是整个应用的配置入口.
(2) public文件夹存放Web应用所需的Image,CSS或者Javascript.
(3) setup.py和setup.cfg用于Web应用的安装部署.
(4) controllers存放路由控制文件.
(5) templates存储Html或者Json的模板文件.
(6) tests存放测试用例.
PS:
在测试环境可以使用pecan serve config.py启动Web应用.
在商用环境下可以部署Pecan的Web应用到Apache等Web服务器.
Object-dispatch for easy routing
以下是一个简单是Web应用示例,示例中Pecan通过修饰器公开接口。
这个示例是使用Pecan开发一个具体的Web应用。
from pecan import expose,request, redirect, response from webob.exc import status_map class BooksController(object): @expose(content_type='text/plain') def index(self): return "Welcome to book section." @expose(content_type='text/plain') def bestsellers(self): return "We have 5 books in the top 10." class CatalogController(object): @expose(content_type='text/plain') def index(self): return "Welcome to the catalog." #books books = BooksController() class RootController(object):
# 默认页面以index.html为模板 @expose(generic=True, template='index.html') def index(self): return dict() # for POST @index.when(method='POST') def index_post_test(self, q): redirect('http://pecan.readthedocs.org/en/latest/search.html?q=%s' % q)
# show error page @expose('error.html') def error(self, status): try: status = int(status) except ValueError: # pragma: no cover status = 500 message = getattr(status_map.get(status), 'explanation', '') return dict(status=status, message=message) # /hello @expose(generic=True, template='index.html') def hello(self): return dict() # /testtext.txt @expose(content_type='text/plain') def testtext(self): return 'text test' # json @expose('json') def jsontest(self): response.status = 200 return {'foo': 'bar'} # catalog catalog = CatalogController()
Full support for REST-style controllers
以下是一个使用Pecan实现的Rest服务.
包括GET,POST,PUT,DELETE.
from pecan import abort, expose # Note: this is *not* thread-safe. In real life, use a persistent data store. BOOKS = { '0': 'The Last of the Mohicans', '1': 'Catch-22' } class BookController(object): def __init__(self, id_): self.id_ = id_ assert self.book @property def book(self): if self.id_ in BOOKS: return dict(id=self.id_, name=BOOKS[self.id_]) abort(404) # HTTP GET /<id>/ @expose(generic=True, template='json') def index(self): return self.book # HTTP PUT /<id>/ @index.when(method='PUT', template='json') def index_PUT(self, **kw): BOOKS[self.id_] = kw['name'] return self.book # HTTP DELETE /<id>/ @index.when(method='DELETE', template='json') def index_DELETE(self): del BOOKS[self.id_] return dict() class RootRestController(object): @expose() def _lookup(self, id_, *remainder): return BookController(id_), remainder # HTTP GET / @expose(generic=True, template='json') def index(self): return [dict(id=k, name=v) for k, v in BOOKS.items()] # HTTP POST / @index.when(method='POST', template='json') def index_POST(self, **kw): id_ = len(BOOKS) BOOKS[id_] = kw['name'] return dict(id=id_, name=kw['name'])