本文主要讲web框架架构会有两种形式,一种装饰器和另外一种正则表达式实现路由。
装饰器
创建WSGI服务类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class WSGIapp(object): # 初始化路由routes def __init__(self): self.routes = {} # routes 装饰器 def route(self,path=None): def decorator(func): self.routes[path] = func return func return decorator # 执行wsgi方法,进行路由验证 def __call__(self,environ,start_response): print 'call' return self.wsgi(environ,start_response) def wsgi(self,environ,start_response): path = environ['PATH_INFO'] # 获取路由地址 print path if path in self.routes: status = '200 OK' # 返回状态200 response_headers = [('Content-Type','text/plain')] start_response(status,response_headers) print self.routes[path]() return self.routes[path]() # 进行路由跳转 else: status = '404 Not Found' # 访问当前地址不在路由数组里返回404 response_headers = [('Content-Type','text/plain')] start_response(status,response_headers) return '404 Not Found!' |
进行路由跳转
1 2 3 4 5 6 7 8 |
app = WSGIapp() # 创建对象 app.route('/') # 创建路由 def index(): # 方法名不能重复 return ['This is index'] # 返回信息 @app.route('/hello') # 创建路由 def hello(): return ['hello'] # 返回信息 |
启动服务
1 2 3 4 |
from wsgiref.simple_server import make_server httpd = make_server('',8000,app) print 'start....' httpd.serve_forever() |
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
class WSGIapp(object): def __init__(self): self.routes = {} def route(self,path=None): def decorator(func): self.routes[path] = func return func return decorator def __call__(self,environ,start_response): return self.wsgi(environ,start_response) def wsgi(self,environ,start_response): path = environ['PATH_INFO'] print path if path in self.routes: status = '200 OK' response_headers = [('Content-Type','text/plain')] start_response(status,response_headers) print self.routes[path]() return self.routes[path]() else: status = '404 Not Found' response_headers = [('Content-Type','text/plain')] start_response(status,response_headers) return '404 Not Found!' app = WSGIapp() @app.route('/') def index(): return ['This is index'] @app.route('/hello') def hello(): return ['hello'] from wsgiref.simple_server import make_server httpd = make_server('',8000,app) print 'start....' httpd.serve_forever() |
运行
正则
创建WSGI服务类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
import re #导入模块 class WSGIapp: headers = [] def __init__(self,urls=()): self.urls = urls self.status = '200 OK' def __call__(self,environ,start_response): x = self.mapping_urls(environ) start_response(self.status,self.headers) if isinstance(x,str): return iter([x]) else: return iter(x) def mapping_urls(self,environ): # 进行正则路由查找 path = environ['PATH_INFO'] # 获取路由地址 for pattern,name in self.urls: m = re.match('^'+pattern+'$',path) if m: args = m.groups() func = globals()[name] return func(*args) return self.notfound() def notfound(self): # 找不到返回404 self.status = '404 Not Found' self.headers = [('Content-Type','text/plain')] return '404 Not Found\n' @classmethod # 定义类方法 def header(cls,name,value): cls.headers.append((name,value)) |
进行路由跳转,定义方法,通过正则匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
def GET_index(*args): WSGIapp.header('Content-Type','text/plain') return 'Welcome!\n' def GET_hello(*args): WSGIapp.header('Content-Type','text/plain') return 'Hello %s!\n' % args urls = [ ('/','GET_index'), ('/hello/(.*)','GET_hello') ] wsgiapp = WSGIapp(urls) |
启动服务
1 2 3 4 5 |
if __name__ == '__main__': from wsgiref.simple_server import make_server httpd = make_server('',8000,wsgiapp) print 'server starting...' httpd.serve_forever() |
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
import re class WSGIapp: headers = [] def __init__(self,urls=()): self.urls = urls self.status = '200 OK' def __call__(self,environ,start_response): x = self.mapping_urls(environ) print x start_response(self.status,self.headers) if isinstance(x,str): return iter([x]) else: return iter(x) def mapping_urls(self,environ): path = environ['PATH_INFO'] for pattern,name in self.urls: m = re.match('^'+pattern+'$',path) if m: args = m.groups() func = globals()[name] return func(*args) return self.notfound() def notfound(self): self.status = '404 Not Found' self.headers = [('Content-Type','text/plain')] return '404 Not Found\n' @classmethod def header(cls,name,value): cls.headers.append((name,value)) def GET_index(*args): WSGIapp.header('Content-Type','text/plain') return 'Welcome!\n' def GET_hello(*args): WSGIapp.header('Content-Type','text/plain') return 'Hello %s!\n' % args urls = [ ('/','GET_index'), ('/hello/(.*)','GET_hello') ] wsgiapp = WSGIapp(urls) if __name__ == '__main__': from wsgiref.simple_server import make_server httpd = make_server('',8000,wsgiapp) print 'server starting...' httpd.serve_forever() |
运行
第一个装饰器的那个实现,怎么实现如下的例子啊:
@app.route(‘XXX/a’)
def a(args):
print args
然后对应url:localhost:8000/xxx/a/args
第一个装饰器的那个实现,怎么实现如下的例子啊:
@app.route(‘XXX/a’)
def a(args):
print args
然后对应url:localhost:8000/xxx/a/args
You know, slavery and genocide STILL happen to this day in Africa, and – hint, hint – it’s not white Republicans doing it. Wh2e1re7;s your outrage over that?
为什么要把headers做成类属性啊。然后还要写一个类方法,而不是实例方法。望大大解释。