动手写一个简单的Web框架(Werkzeug路由问题)
动手写一个简单的Web框架(Werkzeug路由问题)
继承上一篇博客,实现了HelloWorld,但是这并不是一个Web框架,只是自己手写的一个程序,别人是无法通过自己定义路由和返回文本,来使用的,所以在这篇博客中,将实现一个简单的路由自定义功能
首先引入werkzeug中的两个工具,分别是Map,和Rule,需要通过以下代码引入
from werkzeug.routing import Map, Rule
这两个可以完成路由定义和匹配的基本实现,其次,还引入到werkzeug中的Request对象来处理environ
首先,我们看一下Map和Rule的使用:
from werkzeug.routing import Rule, Map
url_map = Map([
Rule('/', endpoint='index', methods=['GET']),
Rule('/about', endpoint='about', methods=['GET']),
])
print(url_map)
上面这段代码定义了一个url_map的对象,它是Map的实例,传入参数是一个列表,在列表里面,存储着路由,我们一个一个来看,Rule中首先传入的是路由参数,代表着访问的路由,然后是methods,用于标记请求的方法,再接着是endpoint,这个参数其实只是给这个路由起一个名字,但是关系确是重大的,我们下一步进行的视图函数的定义以及和路由绑定在一起就离不开endpoint这个参数,它可由使用者自行定义,也可默认为视图函数的函数名。可以看到打印出来的url_map,是路由和endpoint以及methods一一对应的

Map中有一个add方法,可以用于添加新的路由
from werkzeug.routing import Rule, Map
url_map = Map([
Rule('/', endpoint='index', methods=['GET']),
Rule('/about', endpoint='about', methods=['GET']),
])
url_map.add(Rule('/hello', endpoint='hello', methods=['GET']))
print(url_map)
可以看到运行结果

关于路由的匹配问题,可以使用Map的match来进行匹配,用法只需传入路由,即可获取endpoint,在运行前,需要使用Map中的bind,来实例化一个urls,它必需的参数为hostname,还有其他的参数可自行研究,我们需要根据实例化出的urls中的match来实现路由的匹配:
from werkzeug.routing import Rule, Map
url_map = Map([
Rule('/', endpoint='index', methods=['GET']),
Rule('/about', endpoint='about', methods=['GET']),
])
url_map.add(Rule('/hello', endpoint='hello', methods=['GET']))
print(url_map)
urls = url_map.bind('127.0.0.1:5000')
url = '/'
endpoint = urls.match(path_info=url)
print(endpoint)
运行结果

看到,匹配到了路由的endpoint
那么,endpoint要怎么使用呢?
我们在添加视图函数的时候,只是添加了路由,我们对于视图函数的存储还没有实现,其实,这里需要自己定义一个字典,用于存储endpoint和视图函数的键值对,这样,就可以通过获取和存入的endpoint来实现获取和存入视图函数,这部分代码就整合到所有代码中:
from werkzeug.wrappers import Response, Request
from werkzeug.serving import run_simple
from werkzeug.routing import Map, Rule
class Jlask(object):
# 初始化url_map和存储endpoint对应视图函数
# 这里是一个小坑,不能再__init__中初始化,这样会使得在类被调用的时候,执行了初始化的代码,导致原先创建的路由都丢失
url_map = Map([])
endpoint_dict = {}
def dispatch_request(self, request):
# 获取请求的路由
url = request.path
urls = self.url_map.bind('127.0.0.1:5000')
# 匹配得到endpoint
endpoint = urls.match(path_info=url)[0]
# 获取到视图函数处理得结果
view_func = self.endpoint_dict[endpoint](request)
return Response(view_func)
def wsgi_app(self, environ, start_response):
# 启动
# 实例化request,存入environ,这里的request就是werkzeug中对于environ的处理,可以通过request来获取各种请求信息
request = Request(environ)
# 调用dispatch_request解析url,得到对应的视图函数处理的结果
response = self.dispatch_request(request)
return response(environ, start_response)
def __call__(self, environ, start_response):
# 调用到wsgi_app,来执行url对应视图函数
return self. wsgi_app(environ, start_response)
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
# 获取请求方法
methods = options.pop('methods', None)
# 如果没有定义endpoint,就用试图函数的名字
if endpoint is None:
endpoint = view_func.__name__
# 生成rule
# rule: 定义的路由
self.url_map.add(Rule(rule, endpoint=endpoint, methods=methods))
# 存储endpoint对应的视图函数
self.endpoint_dict[endpoint] = view_func
# print(self.endpoint_dict)
# print(self.url_map)
app = Jlask()
def Hello(request):
return "Hello World"
app.add_url_rule(rule='/', view_func=Hello, methods=['GET'])
if __name__ == '__main__':
run_simple('127.0.0.1', 5000, Shortly())
到此就完成了简单得包含路由匹配功能的“Web框架”
更新:
对于自定义的视图函数,需要考虑使用者是否自己构造Response对象,所以需要在dispatch_request中对调用的视图函数返回值进行判断,如果是字符串对象,就构造Response,否则就直接返回
def dispatch_request(self, request):
url = request.path
urls = self.url_map.bind('127.0.0.1:5000')
endpoint = urls.match(path_info=url)[0]
view_func = self.endpoint_dict[endpoint](request)
if isinstance(view_func, str):
return Response(view_func)
else:
return view_func
动手写一个简单的Web框架(Werkzeug路由问题)的更多相关文章
- 动手写一个简单的Web框架(模板渲染)
动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...
- 动手写一个简单的Web框架(HelloWorld的实现)
动手写一个简单的Web框架(HelloWorld的实现) 关于python的wsgi问题可以看这篇博客 我就不具体阐述了,简单来说,wsgi标准需要我们提供一个可以被调用的python程序,可以实函数 ...
- 用Python写一个简单的Web框架
一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...
- 自己动手写一个简单的MVC框架(第一版)
一.MVC概念回顾 路由(Route).控制器(Controller).行为(Action).模型(Model).视图(View) 用一句简单地话来描述以上关键点: 路由(Route)就相当于一个公司 ...
- 写一个简单的Web框架
在.Net中有两种常用的Web开发方式,一种是Asp.Net WebForm,另一种是Asp.Net MVC.我先简单的给大家介绍下这两种开发方式的特点,然后再应用自定义脚本映射,反射,json2te ...
- 自己动手写一个简单的MVC框架(第二版)
一.ASP.NET MVC核心机制回顾 在ASP.NET MVC中,最核心的当属“路由系统”,而路由系统的核心则源于一个强大的System.Web.Routing.dll组件. 在这个System.W ...
- 一个简单的web框架实现
一个简单的web框架实现 #!/usr/bin/env python # -- coding: utf-8 -- __author__ = 'EchoRep' from wsgiref.simple_ ...
- 动手写一个简单版的谷歌TPU-矩阵乘法和卷积
谷歌TPU是一个设计良好的矩阵计算加速单元,可以很好的加速神经网络的计算.本系列文章将利用公开的TPU V1相关资料,对其进行一定的简化.推测和修改,来实际编写一个简单版本的谷歌TPU.计划实现到行为 ...
- 动手写一个简单版的谷歌TPU-指令集
系列目录 谷歌TPU概述和简化 基本单元-矩阵乘法阵列 基本单元-归一化和池化(待发布) TPU中的指令集 SimpleTPU实例: (计划中) 拓展 TPU的边界(规划中) 重新审视深度神经网络中的 ...
随机推荐
- P5110-块速递推【特征方程,分块】
正题 题目链接:https://www.luogu.com.cn/problem/P5110 题目大意 数列\(a\)满足 \[a_n=233a_{n-1}+666a_{n-2},a_0=0,a_1= ...
- 如何基于Security实现OIDC单点登录?
一.说明 本文主要是给大家介绍 OIDC 的核心概念以及如何通过对 Spring Security 的授权码模式进行扩展来实现 OIDC 的单点登录. OIDC 是 OpenID Connect 的简 ...
- JavaWeb#JSP内置对象
[1.JSP内置对象简介] 内置对象:不加声明就可以在JSP页面脚本中使用的成员变量.(使用这些对象可以更容易收集客户端发送的请求信息,响应客户端的请求及存储客户信息.) 主要介绍:out,reque ...
- (目录)Fortran学习笔记:开坑!!!
前言:因为某些原因,需要使用Fortran编写程序,记录下Fortran语法学习过程中的部分笔记.在此开坑记录,立下Flag,"希望年末能够更新完" Fortran 学习笔记 陈橙 ...
- Python Pandas的使用 !!!!!详解
Pandas是一个基于python中Numpy模块的一个模块 Python在数据处理和准备⽅⾯⼀直做得很好,但在数据分析和建模⽅⾯就差⼀些.pandas帮助填补了这⼀空⽩,使您能够在Python中执 ...
- SpringBoot 后端接收前端传值的方法
1.通过HttpServletRequest接收,适用于GET 和 POST请求方式 通过HttpServletRequest对象获取请求参数 @RestController @Reque ...
- python反序列化1(__reduce__)
part1:不求甚解的复现 对于服务端源码: 编写恶意序列化对象生成程序: 将生成的恶意序列化对象输入服务端user,使其执行系统命令.(上面那俩其实都行) part2:原理解释 b'xxx'是 ...
- spring security中动态更新用户的权限
在程序的执行过程中,有时有这么一种需求,需要动态的更新某些角色的权限或某些人对应的权限,当前在线的用户拥有这个角色或拥有这个权限时,在不退出系统的情况下,需要动态的改变的他所拥有的权限. 需求:张三 ...
- elasticsearch的bulk(批量)操作
在es中我们可能会有这么一种需求,即有时需要批量向es中插入或更新或删除数据,如果一条一条数据的操作,那么速度必然很慢,那么es的bulk api就可以派上用场. delete 删除操作,只需要写一个 ...
- 解决svn异常报错“”cleanup failed to process the following paths …… previous operation has not finished”
参考高票答案https://stackoverflow.com/questions/10128201/subversion-stuck-due-to-previous-operation-has-no ...