当前位置: 首页 > 工具软件 > Werkzeug > 使用案例 >

werkzeug基础 - pythonweb(1)

程瑞
2023-12-01
python-web基础 werkzeug

​     werkzeug 是 python WSGI (web server gateway interface, web服务器网关接口) 的应用程序库;werkzeug 没有任何外部依赖项,开发人员可以选择模板引擎、数据库适配器,以及如何处理请求。werkzeug是一个德语名词,译为“工具”的意思;他的作者Armin Ronacher(习惯人们称他为 mitsuhiko) 还着手写了其他的web相关程序库:Jinja2(一个html模板渲染引擎)、Flask(基于werkzeug的高阶web框架)。
​     WSGI 是一个web服务器的规范接口,描述了一个web服务器应该如何处理HTTP请求,并对请求做出响应,PEP333 对webserver网关的功能进行了描述,werkzeug基于此文档实现了一个webserver;这和Java Servlet 平齐,作为http服务器的基础程序,可以快速入手。HTTP协议作为应用层协议,是依赖传输层的TCP协议,传输层的协议可以用socket套接字描述(IP-port), werkzeug使用python网络模块socket接收请求,然后解析HTTP报文,拿到相应的请求数据。werkzeug特性:

  • (1) 全功能的请求对象。包含请求头、查询参数、表单数据、文件、浏览器cookies;
  • (2) 路由系统。将请求的URL与端点相匹配,端点是服务器端一个可调用的函数,路由系统还会将函数的参数捕获,交给函数调用;
  • (3) HTTP实用工具集;用于处理实体Entity、缓存控制、日期、用户代理、浏览器cookies、文件的实用函数。

​     werkzeug 系列文章将会逐一介绍werkzeug的上述特性,用于编写完整的web应用程序,以及通过完整的一个例子编写一个类似于SpringMVC分层的web实例。werkzueug 路由模块可以作为控制层, 视图层(HTML页面)由谁来呈现呢?交由模板渲染引擎Jinja2(可以在html页面使用python语法将应用数据呈现),模型层(实体层) -数据的持久化我们需要借助python数据库操作模块(db-api: pymysql/psycopg2) 来进行。

1.1 安装werkzeug:

​ werkzeug 现在已经发布到了2.0版本(引入了typing, 代码中加入了类型解释,代码不容阅读),我们使用werkzeug的稳定1.0版本,主体程序差别不大。安装:

pip install Werkeug==1.0.0
1.2 第一个werkzeug程序:
def application(environ, start_response):
    from werkzeug.wrappers import Response
    
    response = Response('Hello World!', mimetype='text/plain')
    return response(environ, start_response)


if __name__ == "__main__":
    from werkzeug.serving import run_simple

    run_simple("localhost", 5000, application)
'''
run_simple 用于跑起一个web应用用于监听请求
run_simple(hostname, port, app)
app 必须带有两个参数(environ, start_response)以供调用
对于类来说,__call__(environ, start_reponse),实例化一个对象后,实现对象可函数化调用
app 返回一个Response对象后,调用response(environ, start_response)
'''

1.3 werkzeug路由系统:

​     werkzueg路由系统由werkzueg.routing模块所定义,路由首先需要绑定到适配器上,请求路径的匹配由适配器调用规则Rule的匹配方法;同一个路径,对应不同的请求方法(GET、POST)会匹配出不同的端点,路径是由一个复杂的正则匹配出来的(详解见python正则表达式-语义化正则)。

from werkzeug.routing import Map, Rule

from werkzeug.wrappers import Request, Response
from werkzeug.exceptions import NotFound
from werkzeug.routing import Map, Rule

'''
Rule(string='', methods=["POST", "GET"], endpoint)
endpoint 可以是一个可直接调用的函数,也可以是函数名称(通过getattr()获取并调用)
'''
# 路由的映射可以做为一个全局变量定义使用
url_map = Map([
    Rule('/', endpoint="show"),
    Rule("/about", endpoint="show"),
    Rule("/detail/<id>", endpoint="show"),
    Rule("/home/<int:id>", endpoint="show"),
])
# 一个最完整的url模式,url的匹配通过正则表达式匹配 /path/<type_converter(cvt_args):func_args>
url_map.add(Rule("/page/<string(length=10):id>", endpoint="show"))


class App:

    def show(self, request, id=None):
        path = request.path
        show_str = "This is Error page!"
        if path == "/":
            show_str = "This is Index page!"
        elif path == "/about":
            show_str = "This is About page!"
        elif path.find("/detail") != -1:
            show_str = f"This is No.{id} Detail page!"
        elif path.find("/home") != -1:
            show_str = f"This is NO.{id} Home page!"
        elif path.find("/user") != -1:
            show_str = f"This is NO.{id} User page!"
        return Response(show_str, mimetype="text/plain")

    def dispatch_request(self, environ, start_response):
        request = Request(environ)
        adapter = url_map.bind_to_environ(environ)
        try:
            endpoint, args = adapter.match()
            handler = getattr(self, endpoint)
            response = handler(request, **args)
        except NotFound as e:
            response = e
        return response(environ, start_response)

    def __call__(self, environ, start_response):
        return self.dispatch_request(environ, start_response)


if __name__ == "__main__":
    from werkzeug.serving import run_simple
    application = App()
    run_simple("localhost", 5000, application)
1.4 werkzueg静态资源访问:

​     对于css、js、image等静态资源的访问,werkzueg提供了SharedMiddleWare来将本地路径和请求路径匹配,我们需要将App类用SharedMiddleWare进行装配:

from werkzeug.middleware.shared_data import SharedDataMiddleware
import os

local_static_path = os.path.join(os.path.dirname(__file__), "static")
app = SharedDataMiddleware(app, {"/static":, local_static_path)})

​     当一个带有/static/style.css的请求过来时,sharedmiddleware会在local_static_path下寻找style.css文件,并返回二进制文件流(application/octet-stream)到浏览器。这就会递归将所有local_static_path下的文件暴露到/static请求下,发布了所有静态资源。这个同样可以用于用户上传的图片与文件的访问。

1.5 werkzueg 请求对象Request:

    Request对象会将envrion的上下文环境进行封装,得到一个请求对象,常用的request对象的参数由下表说明:

from werkzeug.wrappers import Request
request = Request(environ)
# 所有的HTTP实体都被封装成了ImmutableMultiDict, 支持字典['key']取, 也支持对象.取, 前提该key存在
# 所有特殊字典都组织在werkzeug.datastructures 模块里,有兴趣可以看一下里面的方法
HTTP实体Request对象参数用法说明
请求路径request.path
地址栏参数request.args
请求方法request.method
客户端地址reqest.remote_addr
表单参数request.form转字典:request.form.to_dict()
提交文件request.files获取文件二进制流: request.files.get(‘img’)->FileStorage
获取多个文件:getlist(‘img’)
存储文件: img.save(dst_path)
客户端cookiesrequest.cookies根据cookies装配session(seesionId)

本篇关于werkzueg基础操作:如何跑起一个webserver、 获取表单数据、处理请求、分派路由,下一篇将是关于python数据库操作。

 类似资料: