cbv分析,模板,请求与响应,session及源码分析,闪现,请求扩展

0|1cbv分析,模板,请求与响应,session及源码分析,闪现,请求扩展

1|0cbv分析

1|1cbv编写视图类的方法

# 导入flask from flask import Flask,request # 导入cbv需要的MethodView from flask.views import MethodView # 实例化flask对象 app=Flask(__name__) app.debug=True # 编写cbv class Indexview(MethodView): # 编写get请求 def get(self): print('get请求进这里') return 'get请求' # 编写post请求 def post(self): print('post请求进这里') return 'post请求' #添加路由 app.add_url_rule('/index',endpoint='index',view_func=Indexview.as_view('index')) if __name__ == '__main__': app.run()

image

1|2cbv源码分析

# 1、IndexView.as_view('index') 执行完的结果,是个函数(view的)内存地址 def as_view(cls, name, *class_args, **class_kwargs): def view(**kwargs: t.Any) -> ft.ResponseReturnValue: # 本质是在执行self.dispatch_request,只是用了异步 return current_app.ensure_sync(self.dispatch_request)(**kwargs) return view # 2、请求来了,执行view()--->本质在执行self.dispatch_request---》MethodView中的 def dispatch_request(self, **kwargs): # self是视图类的对象 meth = getattr(self, request.method.lower(), None) # 用异步执行meth() return current_app.ensure_sync(meth)(**kwargs) # 3、总结: 执行原理和django一样 # 4、路径如果不传别名,别名就是函数名---》分析一下源码 -@app.route('/index')--》没有传endpoint -endpoint 就是None---》调用了app.add_url_rule,传入了None if endpoint is None: endpoint = _endpoint_from_view_func(view_func) # type: ignore -_endpoint_from_view_func 就是返回函数的名字 # 5 as_view('index') 必须传参数,传进来的参数是,是【别名】 # view是as_view内的内层函数,闭包函数 view.__name__ = name # 修改了函数的名字变成了你传入的 # app.add_url_rule('/index',view_func=IndexView.as_view('index')) 简写成:app.add_url_rule('/index',view_func=view) #如果不传参数, 所有人的别名(endpoint),都是内层函数view,所以就报错了

1|3补充及总结

#补充:flask的路由注册使用装饰器,如果写了一个登录认证装饰器,那么应该放在路由装饰器上还是下? -放在路由下面 -路由必须传endpoint,如果不传,又报错
总结: # 1、视图类必须继承MethodView, # 如果继承View,它的dispatch_request没有具体实现,你的视图类必须重写dispatch_request,我们不想重写,继承MethodView def dispatch_request(self) -> ft.ResponseReturnValue: raise NotImplementedError() # 2、视图类加装饰器,直接配置在类属性上【decorators】即可 decorators = [auth,] # 源码,cls是视图类,中有decorators if cls.decorators: for decorator in cls.decorators: view = decorator(view) # view=auth(view) # 源码学到的 -1 as_view 执行流程跟djagno一样 -2 路径如果不传别名,别名就是函数名(endpoint) -3 视图函数加多个装饰器(上下顺序和必须传endpoint) -4 视图类必须继承MethodView,否则需要重写dispatch_request -5 视图类加装饰器:类属性decorators = [auth,]

2|0模板

2|1py文件

# 导入flask from flask import Flask,render_template,Markup #模板的路径必须是templates,因为实例化app对象时,传入的 app=Flask(__name__,template_folder='templates',static_folder='static') # 1、template_folder 可以指定模板的文件(修改模板文件名字) # 2、static_folder 指定静态文件目录 app.debug=True def add(a,b): return a+b @app.route('/') def index(): # 不存在xss攻击,已经解决了 a='<a href="http://www.baidu.com">点我看美女</a>' # 可以用Markup包起来,就可以用不同的safe a=Markup(a) return render_template('index.html',name='lqz',a=a,add=add) if __name__ == '__main__': app.run()

2|2html页面

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>模板语法,static</h1> <img src="/static/10.jpg" alt=""> <h1>模板语法,if</h1> {% if name %} <h1>Hello {{ name }}!</h1> {% else %} <h1>Hello World!</h1> {% endif %} <h1>模板语法,标签渲染</h1> {{a|safe}} {{a}} <h1>模板语法,执行函数</h1> {{add(4,5)}} </body> </html>

3|0请求与响应

3|1请求

# 请求:全局的request对象(需要在全局导入使用)
# request.method 提交的方法 # request.args get请求提及的数据 # request.form post请求提交的数据 # request.values post和get提交的数据总和 # request.cookies 客户端所带的cookie # request.headers 请求头 # request.path 不带域名,请求路径 # request.full_path 不带域名,带参数的请求路径 # request.script_root # request.url 带域名带参数的请求路径 # request.base_url 带域名请求路径 # request.url_root 域名 # request.host_url 域名 # request.host 127.0.0.1:500
from flask import Flask, request, make_response,render_template app = Flask(__name__) app.debug = True @app.route('/', methods=['GET', 'POST']) def index(): #### 请求 print(request.method) print(request.args) print(request.form) print(request.values) print(request.cookies) print(request.headers) print(request.path) print(request.full_path) print(request.url) print(request.base_url) print(request.host_url) print(request.host) obj = request.files['file'] obj.save(obj.filename) if __name__ == '__main__': app.run()

image

3|2响应

from flask import Flask, request, make_response,render_template app = Flask(__name__) app.debug = True @app.route('/', methods=['GET', 'POST']) def index(): # 响应 四件套 # 1 响应中写入cookie response = 'hello' res = make_response(response) # flask.wrappers.Response print(type(res)) res.set_cookie('xx','xx') return res # 2 响应头中写数据(新手四件套,都用make_response包一下) response = render_template('index.html') res = make_response(response) # flask.wrappers.Response print(type(res)) res.headers['yy']='yy' return res if __name__ == '__main__': app.run()

4|0session及源码分析

4|1session的基本使用

# 导入session from flask import Flask,session app=Flask('') # 设置秘钥 app.secret_key='abcccc22' # 存储session @app.route('/',endpoint='set') def set_session(): # 使用提前导入的session return 'session存储完毕' # 获取session @app.route('/index',endpoint='get') def get_session(): #获取session return session.get('name') if __name__ == '__main__': app.run()

4|2session源码分析

# cookie 是存放在客户端浏览器的键值对 # session 是存放在服务器的键值对(在django中存放于session表中) # 在flask中session存放在哪里呢? - flask将session加密后存放到了客户端浏览器阿cookie中,如果session发生了变化,那么浏览器中存放的session也会跟着发生变化 # 源码分析 - 1、app.session_interface 配置了一个类的对象,这个就是session的执行流程 - 2、类中有两个非常重要的方法,请求来了,会执行open_session,请求走了会执行save_session def open_session(self, app, request) : #1 根据名字,取出前端传入的cookie的value值 val = request.cookies.get(self.get_cookie_name(app)) #2 如果没有val,构造了一个空session对象 if not val: return self.session_class() max_age = int(app.permanent_session_lifetime.total_seconds()) try: # 如果没有过期,解码,做成session对象,后续直接用session即可 data = s.loads(val, max_age=max_age) return self.session_class(data) except BadSignature: # 如果过期了,也是空session return self.session_class() def save_session(self, app, session, response) : name = self.get_cookie_name(app) # 取出过期时间,和把session加密转成字符串,放到cookie中 expires = self.get_expiration_time(app, session) val = self.get_signing_serializer(app).dumps(dict(session)) response.set_cookie( name, val, expires=expires, ) # 扩展,想把session放到redis中,mysql中,已经有人帮咱们写了,第三方的,只需要写个类, - 自己写:需要重写open_session,save_session

5|0闪现

# 闪现(flash)用于存放数据 # 作用: 1 可以跨请求,来保存数据 2 当次请求,访问出错,被重定向到其他地址,重定向到这个地址后,拿到当时的错误
# djagno中有这个东西吗? -message框架 # 用法: -设置 闪现 -flash('红红火火恍恍惚惚或或或或') ,可以设置多次,放到列表中 -flash('超时错误',category="debug") 分类存 -获取 闪现 -get_flashed_messages() ,取完就删除 -get_flashed_messages(category_filter=['debug'])分类取 # 本质,加密后,存放在了客户端浏览器的session中

6|0请求扩展

请求扩展类似于django的中间件,当请求进入之前、响应走之后会触发请求扩展,在flask中用请求扩展代替中间件 #请求扩展有: -before_request:请求来了会走,如果他返回了四件套,就结束了 -after_request :请求走了会走,一定要返回response对象 -before_first_request:第一次来了会走 -teardown_request:无论是否出异常,会走 -errorhandler:监听状态码,404 500 -template_global:标签 -template_filter:过滤器

image

from flask import Flask, request, render_template app = Flask(__name__) ###1 before_request 和 after_request # 请求来了,执行一个函数,来的时候从上往下执行 @app.before_request def before(): print('我来了111') return '不让看了' @app.before_request def before1(): print('我来了222') # 请求走了,执行一个函数,走的时候,从下往上执行 @app.after_request def after(response): print('我走了111') return response @app.after_request def after2(response): print('我走了222') return response # 2 项目启动后的第一个请求 @app.before_first_request def first(): print('我的第一次') # 3 teardown_request,无论视图函数是否出错,都会执行它,做错误日志 @app.teardown_request def teardown(e): print(e) print('执行我了') # 4 errorhandler 监听响应状态码,如果符合监听的状态码,就会走它 @app.errorhandler(404) def error_404(arg): return "404错误了" @app.errorhandler(500) def error_500(arg): return "500错误了" ##5 template_global 在模板中直接使用该过滤器 @app.template_global() def add(a1, a2): return a1 + a2 # 6 template_filter @app.template_filter() def db(a1, a2, a3): return a1 + a2 + a3 @app.route('/') def index(): # a = [1, 2, 3] # print(a[9]) return render_template('index1.html') if __name__ == '__main__': app.run()

__EOF__

本文作者泡芙有点甜
本文链接https://www.cnblogs.com/zx0524/p/17291233.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   小王应该在学习!  阅读(86)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示