Loading

西二Python第六轮

运用werkzeug自建框架

一.自建框架信息

1.实现的功能

功能类型 代表名称
程序接受、响应信息以及运行 app.run()
路由以及视图函数处理 app.way('/',methods=['GET'])
请求处理 request
全局变量 g
会话 session
模板以及渲染模板 template
静态文件以及返回静态文件 static
全局current_app current_app

2.运用的原理函数

原理库 函数
werkzeug.serving run_simple
werkzeug.wrappers Request,Response
werkzeug.routing Map,Rule
werkzeug.utils redirect
werkzeug.wsgi SharedDataMiddleware
jinja2 Environment,FileSystemLoader
itsdangerous TimedJSONWebSignatureSerializer
werkzeug.local LocalProxy,LocalStack
os /

二、功能介绍

1.程序接受、响应信息以及运行

在Freedom类中定义程序运行函数fly(),fly()使用run_simple函数进行接口设置,之后每次与服务器的交互都会调用wsgi_app函数,然后会调用下列两个主要函数最后返回响应
wsgi_app->dispatch_request->make_response->Response

wsgi_app函数将服务器传输的environ信息封装到Request、Response中,进行和request相关的工作后调用dispatch_request

dispatch_request函数主要进行查找请求中对应的路由信息并调用路由函数,将返回值再输入make_response函数中进行简单处理以及建立session到响应中,再返回处理后的响应

2.路由以及视图函数处理

在Freedom类__init__中调用Map实例化url_map用于储存路由Rule中的相关信息,再建立初始化一个字典view_functions用于存储函数名与函数的对应关系。

Freedom类中注册路由的函数是register_url需要路由、该路由下函数名、该路由下函数、访问方法参数,register_url中实例化了Rule并将实例加入到url_map中,将函数名与函数对应传入到view_functions,调用register_url就可以创建路由。

我模仿flask也在register_url函数上加上了一个装饰器,装饰器名为way接受路由以及方法作为参数,在way中默认方法为GET,之后会传入函数作为参数调用decorator函数,decorator函数再调用register_url注册路由后返回被输入的函数。

最后提供给用户的视图函数等的形式就是下面这个样子

当与服务器交互时,调用dispatch_request函数从request中提取出请求的路由信息,再从view_functions中得到视图函数、执行视图函数,其中make_response函数是把视图函数的返回值按照分类封装到Response中返回响应,使得用户不用每次都要调用Response,再把响应返回给服务器,这就是我做的简单路由过程。

2.请求处理、全局变量、会话、全局current_app

对这四个的处理在ctx模块和globals模块中,ctx模块中主要分为AppContext类和RequestContext类两个部分,globals模块中调用了LocalProxy,LocalStack支持多线程以及队列操作。在ctx中RequestContext设置了request以及session的内容,AppContext设置了current_app以及g的内容
(1)globals模块
在globals模块中设置了两个栈request_stack、app_stack,然后分别从app_stack和request_stack类中提取出current_app、g以及request、session,在RequestContext的push中已经将对应的RequestContext和AppContext推入栈中,在golobals中提取提取信息函数如下方request方法:

分别将信息提取,将会给每个信息加上LocalProxy进行代理(看的意思似乎是为了不同线程保持独立),这样就可以从gobals中调用四个信息,进行相关的操作了。

(2)ctx模块
RequestContext
RequestContext中包括了request、session的内容,有push和pop方法,在RequestContext的__init__中初始化request将服务器传入的environ信息封装,引入Freedom的实例,再初始化url_adapter和session

在push中将request_stack、app_stack栈顶的信息更换进行信息的更新,并在此时创建session

在push中的session创建我采用了itsdangerous中的TimedJSONWebSignatureSerializer将__init__中初始化的session字典转换成token,push中的create_session函数从引入的app中调用search_session函数从栈顶的request的cookies中得到session编码后的token,编码session的函数是RequestContext的set_token函数,这个函数在Freedom类的dispatch_request函数中被调用并通过response的set_cookies将token建立在cookies中,这样就实现了session。


AppContext
AppContext用RequestContext差不多,先在__init__中初始化g以及引入app,然后AppContext中同样也有push以及pop方法,但AppContext还没有完善只有很少的功能

3.模板以及渲染模板

最初的模板在Freedom的__init__中初始化为文件夹tamplates,模板的设置我从jinja2中调用Environment,FileSystemLoader并jinja_env设置为文件夹tamplates的地址,这样就实现了默认的模板查询地址和存储地址,在Freedom中我设置了一个由用户自定义模板地址的函数set_templates,这个函数需要输入文件夹名作为参数

在Freedom中我也设置了一个渲染模板的函数drawing_template,这个函数从jinja_env中获取模板文件并渲染返回

4.静态文件以及返回静态文件

关于静态文件的地址我再Freedom中建立了一个set_static函数,这个函数在__init__中会被调用并且初始化app_path文件保存地址,默认是static文件夹,用户可以通过这个函数设置提取和设置保存文件的文件夹。在这个函数中我设置了有一个提取文件的路由,之后通过SharedDataMiddleware设置返回静态文件。

5.遇到的问题

在ctx的全局变量g,初始化时我将g初始化为一个空类的实例,但是仍然能实现全局变量的功能

posted @ 2020-05-29 21:56  洋洋羊羊  阅读(174)  评论(0编辑  收藏  举报