flask中的werkzeug介绍

flask中的werkzeug

Werkzeug是一个Python库,用于开发Web应用程序。它是一个WSGI(Web Server Gateway Interface)工具包,提供了一系列实用功能来帮助开发者处理HTTP请求、响应、URLs等等。Werkzeug的设计非常灵活,可以用作构建各种Web框架的基础。

Werkzeug的特性包括:

  • 请求和响应对象:Werkzeug为HTTP请求和响应提供了易于使用的包装器,使得开发者可以更方便地处理这些请求和响应。
  • URL路由:Werkzeug提供了强大的URL路由功能,能够帮助开发者将URL映射到相应的处理函数。(文末进行举例说明)
  • 错误处理:Werkzeug提供了异常处理机制,可以方便地处理HTTP错误,并且提供了一个交互式的调试器,使得在开发过程中调试错误更加方便。
  • HTTP工具:Werkzeug还提供了一些其他的HTTP相关的工具,比如处理cookies、文件上传等。

例子

python 复制代码
from werkzeug.wrappers import Request, Response

def application(environ, start_response):
    request = Request(environ)
    text = 'Hello, %s!' % request.args.get('name', 'World')
    response = Response(text, mimetype='text/plain')
    return response(environ, start_response)

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, application)
python 复制代码
def application(environ, start_response):

这定义了一个函数,名为application。这个函数符合WSGI的规范,是一个典型的WSGI应用。它接受两个参数,environ是一个包含所有HTTP请求信息的字典,start_response是一个发送HTTP响应的回调函数。

python 复制代码
  request = Request(environ)

这行代码用Werkzeug的Request类将environ字典包装为一个Request对象,这样我们就可以方便地通过面向对象的方式访问HTTP请求的信息。

python 复制代码
 text = 'Hello, %s!' % request.args.get('name', 'World')

这行代码从request.args(一个MultiDict,包含所有的查询参数)中获取'name'参数的值,如果没有找到'name'参数,那么就默认为'World'。然后使用这个值生成一段问候语。

python 复制代码
 response = Response(text, mimetype='text/plain')

这行代码创建一个Response对象,它接受两个参数,第一个参数是HTTP响应的主体(在这个例子中是一段问候语),第二个参数是响应的MIME类型,这里设置为'text/plain',表示响应的内容是纯文本。

python 复制代码
return response(environ, start_response)

最后,这行代码调用response对象的__call__方法,传入environstart_response。这样Response对象就会按照WSGI的规范,调用start_response发送HTTP响应。因为Response类是可调用的,所以我们可以将其作为WSGI应用返回。

要发送带有 'name' 参数的请求,你只需要在URL中添加一个查询参数即可。例如,如果你的服务器运行在localhost的4000端口上,你可以通过以下URL发送请求:

python 复制代码
http://localhost:4000/?name=YourName

在这个URL中,'?' 后面的部分是查询参数。你可以通过更改 'YourName' 来改变 'name' 参数的值。例如,如果你将 'YourName' 改为 'Alice',那么服务器将会响应 'Hello, Alice!'。

werkzeug的路由系统

在 Werkzeug 中,路由的处理主要通过 werkzeug.routing 模块中的 MapRule 类来实现。下面是一个简单的示例:

python 复制代码
from werkzeug.routing import Map, Rule
from werkzeug.wrappers import Request, Response

# 创建一个 URL 映射
url_map = Map([
    Rule('/', endpoint='hello'),  # 将根路径 / 映射到 'hello' 端点
    Rule('/bye', endpoint='bye')  # 将 /bye 路径映射到 'bye' 端点
])

# 创建处理函数字典
view_functions = {
    'hello': lambda: Response('Hello, World!'),
    'bye': lambda: Response('Goodbye, World!')
}

# 创建 WSGI 应用
def application(environ, start_response):
    request = Request(environ)
    urls = url_map.bind_to_environ(request.environ)  # 将环境绑定到 URL 映射
    endpoint, args = urls.match()  # 从 URL 映射中匹配请求路径
    response = view_functions[endpoint]()  # 使用相应的处理函数处理请求
    return response(environ, start_response)

# 在主程序中运行 WSGI 服务器
if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, application)

在这个例子中,我们首先创建了一个 Map 对象,它包含了两个 Rule。每个 Rule 都定义了一个 URL 模式和一个对应的端点。然后,我们创建了一个字典 view_functions,它将每个端点映射到一个处理函数。

然后,我们创建了一个 WSGI 应用 application。这个应用首先使用 Map.bind_to_environ 方法将请求环境绑定到 URL 映射,然后使用 MapAdapter.match 方法从 URL 映射中匹配请求路径,最后使用相应的处理函数处理请求。

最后,我们在主程序中使用 run_simple 函数运行一个 WSGI 服务器,将 application 作为处理函数。这样,当你访问 http://localhost:4000/ 时,你将看到 'Hello, World!',当你访问 http://localhost:4000/bye 时,你将看到 'Goodbye, World!'。

重点

pyth 复制代码
urls = url_map.bind_to_environ(request.environ) 

这行代码的作用是创建一个 MapAdapter 对象。 MapAdapter 对象是 Werkzeug 路由系统的关键组成部分,它的主要任务是根据当前的请求环境,匹配最合适的 URL 规则。

这里的 request.environ 是一个字典,包含了所有的 WSGI 环境变量,例如 HTTP 方法、路径、查询参数等。当我们调用 url_map.bind_to_environ(request.environ) 时,Werkzeug 实际上是在创建一个能够理解当前请求环境的 MapAdapter 对象。

然后,你就可以在这个 MapAdapter 对象上调用 match() 方法,来匹配当前请求的 URL。如果找到了匹配的规则,match() 方法会返回一个包含端点名称和路径参数的元组。

假设我们访问 "http://localhost:4000/bye" 这个 URL,那么在 application 函数中:

  1. request = Request(environ):这行代码将请求环境包装成一个 Request 对象,方便我们访问请求相关的信息。
  2. urls = url_map.bind_to_environ(request.environ):这行代码将当前的请求环境(包括 HTTP 方法、路径 '/bye' 等)绑定到 url_map 上,并返回一个 MapAdapter 对象 urlsurls 了解如何将请求环境与 url_map 中定义的 URL 规则进行匹配。
  3. endpoint, args = urls.match():这行代码在 urls 中查找匹配当前请求环境的 URL 规则。在这个例子中,它找到了规则 Rule('/bye', endpoint='bye'),并返回其对应的端点 'bye'
  4. response = view_functions[endpoint]():这行代码查找与端点 'bye' 对应的处理函数(即 view_functions['bye']),并调用这个函数处理请求。在这个例子中,处理函数返回了一个 Response 对象,其内容为 'Goodbye, World!'
  5. return response(environ, start_response):这行代码将响应返回给客户端。

所以,url_map.bind_to_environ(request.environ) 的作用就是创建一个 MapAdapter 对象,这个对象能够根据当前的请求环境,在 url_map 中找到匹配的 URL 规则。

MapAdapter类介绍

MapAdapter是Werkzeug路由系统中的一个重要类,用于处理URL规则与具体请求之间的匹配与生成URL。以下是MapAdapter中的一些重要的方法和属性:

  • match(path_info=None, method=None): 尝试匹配给定的路径和方法(如果提供)与 Map 中的 Rule 规则。如果找到匹配的规则,这个方法会返回一个元组,包含端点名称和路径参数。如果没有找到匹配的规则,这个方法会抛出 NotFound 异常。如果找到了多个匹配的规则,这个方法会抛出 MethodNotAllowed 异常。
  • build(endpoint, values=None, method=None, force_external=False, append_unknown=True): 生成一个URL,该URL与指定的端点和值匹配。这个方法在你需要生成应用内的URL时非常有用,例如在重定向或链接生成时。
  • bind_to_environ(environ, server_name=None): 生成一个新的 MapAdapter,该 MapAdapter 是当前 MapAdapter 的副本,但绑定到给定的WSGI环境。这在处理请求时非常有用,因为它可以创建一个理解当前请求的 MapAdapter
  • bind(server_name, script_name=None, subdomain=None, url_scheme='http', default_method='GET'): 生成一个新的 MapAdapter,该 MapAdapter 是当前 MapAdapter 的副本,但绑定到指定的服务器名称、脚本名称、子域名和URL方案。这在你需要在不同环境中测试路由系统时非常有用。

此外,MapAdapter还包含一些用于配置路由系统的属性,例如 map(与 MapAdapter 关联的 Map 对象)、server_name(服务器的名称)和 url_scheme(URL的方案,通常是 'http' 或 'https')。

MapAdapter 本身并不存储任何请求或响应信息。它的主要任务是理解如何将请求匹配到 Map 中的 Rule 规则,并根据这些规则生成URL。

相关推荐
Tech Synapse4 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
.生产的驴5 分钟前
SpringCloud OpenFeign用户转发在请求头中添加用户信息 微服务内部调用
spring boot·后端·spring·spring cloud·微服务·架构
微信-since8119220 分钟前
[ruby on rails] 安装docker
后端·docker·ruby on rails
肥猪猪爸22 分钟前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
LZXCyrus1 小时前
【杂记】vLLM如何指定GPU单卡/多卡离线推理
人工智能·经验分享·python·深度学习·语言模型·llm·vllm
Enougme1 小时前
Appium常用的使用方法(一)
python·appium
懷淰メ1 小时前
PyQt飞机大战游戏(附下载地址)
开发语言·python·qt·游戏·pyqt·游戏开发·pyqt5
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
hummhumm2 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
每天吃饭的羊2 小时前
python里的数据结构
开发语言·python