Werkzeug是Python的WSGI规范的实用函数库。使用广泛,基于BSD协议。
Flask底层就是使用了Werkzeug。
完整代码:
https://github.com/yangzhezjgs/Light/tree/master/webapp
Python版本:
最好使用Python3,Python2需要修改except HTTPException as e 为except HTTPException , e
总体思想
通过url_map这个字典建立url和处理url的视图函数之间的映射关系。
思路参考Werkzeug给出的官方示例:
https://github.com/pallets/werkzeug/blob/0.12.2/examples/webpylike/webpylike.py
关键点:
add_url_rule方法调用,导致视图类通过调用类方法,返回一个闭包,闭包返回一个视图函数,于是建立了url与视图函数的映射关系。
run_simple启动一个wsgi服务器,self参数调用自身(因为实现__call__
方法,对象变为可调用对象)
代码
from werkzeug.wrappers import BaseRequest, BaseResponse
from werkzeug.exceptions import HTTPException, MethodNotAllowed, \
NotImplemented, NotFound
from werkzeug.serving import run_simple
class Request(BaseRequest):
"""Encapsulates a request."""
class Response(BaseResponse):
"""Encapsulates a response."""
class View(object):
"""Baseclass for our views."""
def __init__(self):
self.methods_meta = {
'GET': self.GET,
'POST': self.POST,
'PUT': self.PUT,
'DELETE': self.DELETE,
}
def GET(self):
raise MethodNotAllowed()
POST = DELETE = PUT = GET
def HEAD(self):
return self.GET()
def dispatch_request(self, request, *args, **options):
if request.method in self.methods_meta:
return self.methods_meta[request.method](request, *args, **options)
else:
return '<h1>Unknown or unsupported require method</h1>'
@classmethod
def get_func(cls):
def func(*args, **kwargs):
obj = func.view_class()
return obj.dispatch_request(*args, **kwargs)
func.view_class = cls
return func
class WebApp(object):
def __init__(self):
self.url_map = {}
def __call__(self, environ, start_response):
try:
req = Request(environ)
url = req.path
view = self.url_map.get(url, None)
if view:
response = view(req)
response = Response(response)
else:
response = Response('<h1>404 Source Not Found<h1>', content_type='text/html; charset=UTF-8', status=404)
except HTTPException as e:
response = e
return response(environ, start_response)
def add_url_rule(self,urls):
for url in urls:
self.url_map[url['url']] = url['view'].get_func()
def run(self, port=5000, ip='', debug=False):
run_simple(ip, port, self, use_debugger=debug, use_reloader=True)
使用示例
from webapp import WebApp,View
class Index(View):
def GET(self,request):
return "hello world"
class Test(View):
def GET(self,request):
return "test"
urls = [
{
'url':'/',
'view':Index
},
{
'url':'/test',
'view':Test
}
]
app = WebApp()
app.add_url_rule(urls)
app.run()