动手写一个简单的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路由问题)的更多相关文章

  1. 动手写一个简单的Web框架(模板渲染)

    动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...

  2. 动手写一个简单的Web框架(HelloWorld的实现)

    动手写一个简单的Web框架(HelloWorld的实现) 关于python的wsgi问题可以看这篇博客 我就不具体阐述了,简单来说,wsgi标准需要我们提供一个可以被调用的python程序,可以实函数 ...

  3. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  4. 自己动手写一个简单的MVC框架(第一版)

    一.MVC概念回顾 路由(Route).控制器(Controller).行为(Action).模型(Model).视图(View) 用一句简单地话来描述以上关键点: 路由(Route)就相当于一个公司 ...

  5. 写一个简单的Web框架

    在.Net中有两种常用的Web开发方式,一种是Asp.Net WebForm,另一种是Asp.Net MVC.我先简单的给大家介绍下这两种开发方式的特点,然后再应用自定义脚本映射,反射,json2te ...

  6. 自己动手写一个简单的MVC框架(第二版)

    一.ASP.NET MVC核心机制回顾 在ASP.NET MVC中,最核心的当属“路由系统”,而路由系统的核心则源于一个强大的System.Web.Routing.dll组件. 在这个System.W ...

  7. 一个简单的web框架实现

    一个简单的web框架实现 #!/usr/bin/env python # -- coding: utf-8 -- __author__ = 'EchoRep' from wsgiref.simple_ ...

  8. 动手写一个简单版的谷歌TPU-矩阵乘法和卷积

    谷歌TPU是一个设计良好的矩阵计算加速单元,可以很好的加速神经网络的计算.本系列文章将利用公开的TPU V1相关资料,对其进行一定的简化.推测和修改,来实际编写一个简单版本的谷歌TPU.计划实现到行为 ...

  9. 动手写一个简单版的谷歌TPU-指令集

    系列目录 谷歌TPU概述和简化 基本单元-矩阵乘法阵列 基本单元-归一化和池化(待发布) TPU中的指令集 SimpleTPU实例: (计划中) 拓展 TPU的边界(规划中) 重新审视深度神经网络中的 ...

随机推荐

  1. 开启Nginx代理HTTPS功能

    1.首先查看是否已经安装SSL openssl version -a 2.生成SSL证书 在nginx目录下创建ssl文件夹 cd /etc/pki mkdir nginx cd nginx 生成20 ...

  2. iOS自定义拍照框拍照&裁剪(一)

    卡片机时代 很重要的一点是,相机本身是没有方向概念的,它不理解拍摄的内容,只会以相机自己的坐标系去保存数据,下图展示了相机对"F"进行四个角度拍摄时返回的图片数据. 最初的卡片机时 ...

  3. 详解build-gradle文件

    目录 gradle 两个build.gradle文件 最外层目录下的build.gradle文件 jcenter dependencies闭包 app目录下的build.gradle文件 com.an ...

  4. bash手册

    目录 bash手册 man命令 man man 分页程序(page) Linux手册页惯用的节名 Linux手册页的内容区域 查看命令在Linux手册页中的区域 info页面 help帮助 bash手 ...

  5. 初识Tomcat源码

    Tomcat 部署的三种方式 打包成war包 部署到webapp目录录下 为什么要打包成war包,而不是jar包呢? 因为jar包可能是一个项目,也可能是一个依赖,Tomcat读取容易造成混淆.于是一 ...

  6. 【UE4 C++】UGameplayStatics 源代码

    // Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" # ...

  7. 利用 pip 安装 Python 程序包到个人用户文件夹下

    利用 --user 参数,即 pip install --user package_name 这样会将Python 程序包安装到 $HOME/.local 路径下,其中包含三个字文件夹:bin,lib ...

  8. NodeJs安装与环境配置

    https://blog.csdn.net/qq_43285335/article/details/90696126 https://www.cnblogs.com/liuqiyun/p/813390 ...

  9. (一)、Docker 简介

    1.Docker镜像是什么? 镜像是一种轻量级.可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码.运行时.库.环境变量和配置文件. 2.Do ...

  10. 简单易懂讲IO

    流式 IO 是传统 IO,通过构造输入输出流,讲信息从一个地方读取,输出到另一个地方.常见的有读取文件以及写入文件. 基本 API 流失 IO 基本可以分为两个门派,一个以 InputStream 和 ...