cbv分析
视图函数
from flask import Flask, request
from flask.views import View, MethodView
app = Flask(__name__)
app.debug = True
class IndexView(MethodView):
def get(self):
print(request.method)
return 'get请求'
def post(self):
print(request.method)
return 'post请求'
app.add_url_rule('/index', endpoint='index', view_func=IndexView.as_view('index'))
if __name__ == '__main__':
app.run()
源码分析
1.
# IndexView.as_view('index')执行完的的结果是父类View中的as_view里面的view函数
def as_view(
cls, name: str, *class_args, **class_kwargs
) -> ft.RouteCallable:
def view(**kwargs: t.Any) -> ft.ResponseReturnValue:
# 实际上是使用异步执行了self.dispatch_request
return current_app.ensure_sync(self.dispatch_request)(**kwargs)
return view
2.
# 请求来了执行函数view(),实际上是执行了MethodView中的dispatch_request
def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue:
# self是视图类的对象
meth = getattr(self, request.method.lower(), None)
# meth()是使用异步执行的
return current_app.ensure_sync(meth)(**kwargs)
3. 路径如果不传别名,那么就以函数名作为别名
[email protected]('/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 就是返回函数的名字
4.as_view('index')必须传参数,传过来的参数是别名
app.add_url_rule('/index',view_func=IndexView.as_view('index'))
在as_view函数中有一个内层的闭包函数view,他里面有一句代码
view.__name__ = name # 将函数名修改为我们传入的名字
所以我们就可以简写成
app.add_url_rule('/index',view_func=view)
# 如果有多个视图函数,都不传参数的话,所有的别名都是内层函数view,会报错,所以在多个视图函数的情况下传入不同的别名
5.我们的视图类必须继承methodView,如果直接继承View,没有dispatch_request,我们就需要自己重写dispatch_request
6.视图类加装饰器,直接在类属性上配置decorators就行了
decorators = [auth,]
# 源码,cls是视图类,中有decorators
if cls.decorators:
for decorator in cls.decorators:
view = decorator(view) # view=auth(view)
总结:
1.as_view的执行流程与django一样
2.路径如果不传别名,那么别名就是函数名
3.视图函数加多个装饰器,必须传endpoint,还需要注意装饰器的顺序
4.视图类必须继承MethodView,否则重写dispatch_request
5.视图类加装饰器:类属性decorators = [auth,]
模板
from flask import Flask, render_template, Markup
app = Flask(__name__, template_folder='templates', static_folder='static')
app.debug = True
def add(a, b):
return a + b
@app.route('/')
def index():
a = '<a href="http://www.baidu.com">点击</a>'
a = Markup(a)
return render_template('index.html', name='zyg', a=a, add=add)
if __name__ == '__main__':
app.run()
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>模板语法,if</h1>
{% if name %}
<h1>Hello {{ name }}</h1>
{% else %}
<h1>ByeBye</h1>
{% endif %}
<h1>模板语法,标签渲染</h1>
{{ a|safe }}
{{ a }}
<h1>模板语法,执行函数</h1>
{{ add(11,22) }}
</body>
</html>
请求与响应
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)
# 响应头中写数据都用make_response包一下
response = render_template('index.html')
res = make_response(response)
res.headers['yy'] = 'yy'
if __name__ == '__main__':
app.run()
总结:
request.method 提交的方法
request.args get请求提及的数据
request.form post请求提交的数据
request.values post和get提交的数据总和
request.cookies 客户端所带的cookie
request.headers 请求头
request.path 不带域名,请求路径
request.full_path 不带域名,带参数的请求路径
request.url 带域名带参数的请求路径
request.base_url 带域名请求路径
request.url_root 域名
request.host_url 域名
request.host 127.0.0.1:500
session及源码分析
session的使用
from flask import Flask, request, session, render_template, redirect
app = Flask(__name__)
app.debug = True
app.secret_key = 'sfdregxdfgdfsshsdcvasdfsa'
@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
return redirect('/index')
@app.route('/index', methods=['GET', 'POST'])
def index():
return 'hello %s' % session.get('name', '匿名用户')
if __name__ == '__main__':
app.run()
源码分析
cookie是放在客户端浏览器中的键值对
session在diango中是放在服务端的键值对,django中放在了django_session表中
在flask中session则是加密后放在了cookie中
源码:
1.app.session_interface 配置了一个类的对象,它是session的执行流程
2.类中有两个方法,请求来的时候会执行open_session,请求走的时候会执行save_session
def open_session(self, app, request):
# 根据名字取出前端传入的cookie的value值
val = request.cookies.get(self.get_cookie_name(app))
# 如果没有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,
)
闪现
其实就是flash
它其实就是当次请求先把一些数据放在某个位置,然后下一次请求净这些数据取出来,数据取出来以后就没了,不能再次取用,相当于一次性存储
flash作用
1.可以跨请传递数据或保存数据
2.当次请求错误重定向到其他地址,可以拿到当时的错误
用法:
设置
1.flash(),可以设置多次放到一个列表中
2.flash(category='debug') 分类存
获取
1.get_flashed_messages() 取完就删除
2.get_flashed_messages(category_filter=['debug']) 分类取
请求扩展
类似于django的中间件,请求来的时候或走的时候可以绑定一些函数,到这里就会触发执行对应的函数
flask中就用请求扩展来代替django中的中间件
请求扩展分类:
1.before_request 请求来的时候会走,如果返回的是四件套就结束
# 请求来的时候是从上往下执行
2.after_request 请求走的时候会走,返回response对象
# 请求走的时候是从下往上执行
3.before_first_request 请求第一次来会走,之后就不走了
4.teardown_request 无论是否出异常都会走,通常用来做错误日志
5.errorhandler 监听状态码,通常用来做统一异常处理
6.template_global:标签
7.template_filter:过滤器
标签:__,name,flask,app,request,session,使用,view
From: https://www.cnblogs.com/zyg111/p/17284518.html