flask CBV写法/中间件/异常捕获/请求与响应/session/请求扩展
flask cbv写法
基于类的视图写法
from flask import Flask, request
from flask.views import MethodView, View
app = Flask(__name__)
app.debug = True
# 必须要继承MethodView这个类来编写
class LoginView(MethodView):
def get(self):
print(request.method)
return 'get'
def post(self):
print(request.method)
return 'post'
app.add_url_rule('/login', view_func=LoginView.as_view('login'), endpoint='login')
# 对视图函数添加路由,
# Login.as_view('必须传参数') 传入的参数会被当作别名,endpoint是别名的意思 当然也可以不传
# 别名是项目中不可以重复的
-1 as_view 执行流程跟djagno一样
-2 路径如果不传别名(endpoint属性),别名默认是as_view('login')的传参数
-3 视图函数加多个装饰器(上下顺序和必须传endpoint)
例如:你加入了一个验证是否登录的装饰器
@app.route('/home', methods=['GET', 'POST'],endpoint='home')
@login
def home():
return 'home'
使用装饰器,如果再加认证装饰器,那么应该放在路由装饰器上还是下?
-放在路由下面
-路由必须传endpoint,如果不传,又报错
-4 视图类必须继承MethodView,否则需要重写dispatch_request
-5 视图类加装饰器:类属性decorators = [auth,]
if __name__ == '__main__':
app.run()
# app.run('127.0.0.1',5000)
# 可以设置访问地址和端口号,不写默认本地5000端口
视图类加装饰器
from flask import Flask, request
from flask.views import MethodView, View
app = Flask(__name__)
app.debug = True
# 必须要继承MethodView这个类来编写
# 8 视图类加装饰器,直接配置在类属性上【decorators】配置即可
class LoginView(MethodView):
decorators = [auth,]
# 就会把下面的函数当作是参数 传入 auth中
def get(self):
print(request.method)
return 'get'
def post(self):
print(request.method)
return 'post'
app.add_url_rule('/login', view_func=LoginView.as_view('login'), endpoint='login')
模版
前后端一体的flask项目 前端的模版要统一放在 templates文件夹中
from flask import Flask, render_template,Markup
a='<a href="http://www.baidu.com">点我看美女</a>
如果是一个标签需要渲染的话 可以使用 Markup方法
a=Markup(a)
这样包裹传递到前端就可以直接当作链接使用了
也可以传递一个函数到前端
def add(a,b):
return a+b
{{add(4,5)}}
# 前端可以直接使用这个函数 传递参数即可 会得到函数的返回值
return render_template('index.html',name='lqz',a=a,add=add)
# 通过render_template方法可以 渲染出页面 并直接可以给页面传递数据,
请求与响应
请求:全局的request对象
from flask import Flask, request
@app.route('/', methods=['GET', 'POST'])
def index():
#### 请求
# request.method 提交的方法 get/post
# request.args get请求提及的数据 请求头传递的数据
# request.form post请求提交的数据 请求体里面的数据
# request.values post和get提交的数据总和
# request.cookies 客户端所带的cookie
# request.headers 请求头 kv形式 可以通过 User-Agent拿到访问设备
# Host是访问网址和端口,
# 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
obj = request.files['file']
# 这样可以直接把文件拿出来 ['上传的文件名']
obj.save(obj.filename)
# 然后把这个文件直接保存到当前路径下
from flask import Flask, request,make_response
响应中写数据
把需要返回的响应内容包装成一个对象 用make_response方法
然后在这个对象中添加 cookie 或 其他数据
response = 'hello'
res = make_response(response)
res.set_cookie('xx':'xx')
res.headers['yy']='yy'
# 响应头中加入数据
return res
session的使用
cookie:存放在客户端的键值对
session:存放在客户端的键值对
token:存放在客户端,通过算法来校验
from flask import session
当用户登录成功以后可以直接将一些数据 保存到session中
session都是以kv键值对的形式存储在前端的
'''
虽然是全局导入的session 但是每一个请求的session都是不一样的
'''
app.secret_key = 'asdfas33asdfasf'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
name = request.form.get('name')
password = request.form.get('password')
session['name'] = name
# 设置session的方法 k为name valus为name的
return redirect('/index')
@app.route('/index', methods=['GET', 'POST'])
def index():
return 'hello %s' % session.get('name', '匿名用户')
# 取出前端session中 的name ,如果没有默认值为 匿名用户
# 取出session的方法
设置:session['username'] = 'xxx'
删除:session.pop('username', None)
取值:session.get('name', '匿名用户')
session的源码
有两个非常重要的方法,请求来了,会执行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自己写
闪现
跨请求存储数据,例如第一次请求获得了一个数据,第二次请求可以再取出来
实现了跨请求存储数据。
from flask import flash,get_flashed_messages
当次请求,访问出错,被重定向到其他地址,重定向到这个地址后,拿到当时的错误
存数据 多次存储默认是尾部追加
flash('%s,我存了'%name)
获取数据 取的话一次性就会获取所有之前存的数据 并且会把数据删除 只能拿一次
get_flashed_messages()
-假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息
flash('超时错误',category="x1")
设置一个键为x1 值为 超时错误的键值对
data = get_flashed_messages(category_filter=['x1'])
取出键值为x1的值
请求扩展(中间件)
请求来执行,请求走执行
你对那个函数装上当请求来了或者走的时候就会执行哪个函数
如果在请求来的时候 直接返回return那就不会再往下走 就走不到视图函数了
1.before_request
请求来的时候
#基于它做用户登录认证
@app.before_request
# 装上了这个装饰器,那么请求来的时候就会执行这个代码
def process_request(*args,**kwargs):
if request.path == '/login':
return None
user = session.get('user_info')
if user:
return None
return redirect('/login')
2.after_request
请求走的时候
@app.after_request
def index1(response):
# 必须要传参数response
print('请求走了')
return response
@app.before_request
def index():
print('请求来了')
@app.before_request
def index2():
print('请求来了2')
@app.after_request
def index1(response):
# 必须要传参数response
print('请求走了')
return response
@app.after_request
def index1(response):
# 必须要传参数response
print('请求走了2')
return response
请求来时时从上倒下。 请求走时 从下到上
执行顺序:请求来了,请求来了2,请求走了2,请求走了
3.teardown_request
@app.teardown_request
def teardown(error):
print(error)
# 当函数被执行时就会触发这个代码 可以用来记录日志
全局异常捕获
捕捉错误响应码的
@app.errorhandler(403)
def error_404(arg):
return "禁止访问"
@app.errorhandler(404)
def error_404(arg):
return "404请求资源不存在"
@app.errorhandler(500)
def error_404(arg):
return "500错误了"
@app.errorhandler(503)
def error_404(arg):
return "503服务器维护中"
@app.errorhandler(504)
def error_404(arg):
return "504网络延迟"
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了