利用python的werkzeug写的一个简单web框架。实现的功能有路由、各种HTTP方法、获取提交的数据、后端自动重启、模板引擎等。默认运行在127.0.0.1:5000上,操作模式也尽量向Flask靠拢。
废话不多说,上代码
1 import os 2 from werkzeug.wrappers import Response, Request 3 from werkzeug.serving import run_simple 4 from werkzeug.routing import Map, Rule 5 from werkzeug.exceptions import HTTPException, MethodNotAllowed 6 from jinja2 import Environment, FileSystemLoader 7 8 """ 9 定义一个Route类来管理url_map以及请求方式. 10 并加入__call__函数,使得可以直接对对象使用诸如Route()的操作. 11 __call__函数中再使用装饰器,这样操作起来就和Flask一样了 12 endpoint使用了对应的函数名. 13 从参数中获取并储存HTTP请求方法 14 """ 15 class Route: 16 def __init__(self): 17 self.url_map = Map([]) 18 self.endpoint_dict = {} 19 self.methods_list = [] 20 21 def __call__(self, rules,**kwargs): 22 def wrapper(func): 23 endpoint = func.__name__ 24 self.url_map.add(Rule(rules, endpoint=endpoint)) 25 self.endpoint_dict[endpoint] = func 26 for key, value in kwargs.items(): 27 if key == 'methods': 28 self.methods_list = value 29 return func 30 return wrapper 31 32 """ 33 定义了一个Application类 34 """ 35 class Application(): 36 37 def __init__(self): 38 self.route = Route()#调用Route类 39 40 def __call__(self, environ, start_response): 41 return self.application(environ, start_response) 42 43 def run(self,host='127.0.0.1',port=5000,use_reloader=False):#用run_simple定义一个运行方法 44 run_simple(host, port, self, use_reloader=use_reloader) 45 return 46 47 @Request.application 48 def application(self, request): 49 self.urls = self.bind_to_environ(request.environ) 50 if request.method not in self.route.methods_list:#如果请求方法不正确则返回MethodNotAllowed页面 51 raise MethodNotAllowed 52 try: 53 endpoint, args = self.urls.match()#匹配请求参数 54 except HTTPException as e:#如果找不到url则返回404 55 return e 56 return Response(self.route.endpoint_dict[endpoint](request), mimetype='text/html')#响应请求,类型应为'text/html' 57 58 def bind_to_environ(self, env):#用以绑定环境 59 return self.route.url_map.bind_to_environ(env) 60 61 def getdata(self, arg, *instead):#获取数据,如果没有对应数据则返回instead的值,类似request.get('ex1','ex2') 62 values = self.urls.match()[1] 63 try: 64 return values[arg] 65 except: 66 if instead[0] or instead[0] == '': 67 values[arg] = instead[0] 68 return values[arg] 69 70 """ 71 依然是render_template 72 将templates文件夹绑定了jinja2的环境 73 通过获取templates里html文件的文本并通过Application里方法响应到客户端 74 """ 75 def render_template(template_name, **context): 76 template_path = os.path.join(os.getcwd(), 'templates') 77 jinja_env = Environment(loader=FileSystemLoader(template_path), 78 autoescape=True) 79 t = jinja_env.get_template(template_name) 80 return t.render(context)web.py
测试代码
1 from web import Application,render_template 2 3 app = Application() 4 5 @app.route('/',methods=['GET','POST']) 6 def index(request): 7 id = app.getdata('id','abaa') 8 pid = app.getdata('id','') 9 print('id =',id) 10 print('pid =',pid) 11 return render_template('index.html',aa=id,cc='ddd',list=['1','3','2','4']) 12 13 @app.route('/id/<int:id>') 14 def id(request): 15 id = app.getdata('id') 16 return "id is: %s" % id 17 18 @app.route('/current_url') 19 def current_url(request): 20 url = app.urls.build("current_url") 21 return "current url is %s" % url 22 23 app.run(use_reloader=True)app.py
测试模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> hhhhh<br> {{aa}}<h1>{{cc}}</h1> {% if cc %} {{aa}}<h3>{{list}}</h3> {%endif%} {%for i in list %} {{i}}<br> {%endfor%} </body> </html>index.html
项目地址:https://github.com/1113896152/py-web