1.cbv写法
1.定义一个类继承MethodView
2.在定义的类中写与请求方式同名的方法
3.注册路由
from flask import Flask, render_template
app = Flask(__name__, template_folder='templates')
app.debug = True
def auth(func):
def inner(*args, **kwargs):
res = func(*args, **kwargs)
print('装饰器执行了')
return res
return inner
# 基于类的视图
from flask.views import MethodView
# 1.定义一个类
class Home(MethodView):
# 2.在类中写与请求方式同名的方法
def get(self):
return render_template('home.html')
def post(self):
return '猫猫的get请求'
# app.add_url_rule('/home',endpoint='',view_func=Home.as_view())
# 3.注册路由
app.add_url_rule('/home', view_func=Home.as_view('home'))
if __name__ == '__main__':
app.run(port=8080)
2.cbv加装饰器
1.使用decorators= [auth]直接加在类下即可
2.使用语法糖加在方法之前,与直接加在函数上有区别
加在函数上装饰器的参数就是被装饰的函数
加载类的方法之前第一个参数是self
方法一
from flask import Flask, render_template
app = Flask(__name__, template_folder='templates')
app.debug = True
# 自己定义的装饰器
def auth(func):
def inner(*args, **kwargs):
res = func(*args, **kwargs)
print('装饰器执行了')
return res
return inner
from flask.views import MethodView
class Home(MethodView):
# 多个装饰器继续往后写
decorators = [auth]
# app.add_url_rule('/home',endpoint='',view_func=Home.as_view())
app.add_url_rule('/home', view_func=Home.as_view('home'))
if __name__ == '__main__':
app.run(port=8080)
方法二
class Home(MethodView):
methods = ['GET']
@auth
def get(self):
return render_template('home.html')
def post(self):
3. 允许的请求方式
class Home(MethodView):
# 使用methods在列表后继续追加即可
methods = ['GET']
4. cbv源码分析
把代码删减到咱们能读懂 再来分析
# View的as_view方法
@classmethod
def as_view(
def view(**kwargs: t.Any) -> ft.ResponseReturnValue:
return self.dispatch_request(**kwargs)
if cls.decorators:
# cls就是我们自己定义的视图类
# decorators是配置在类下的装饰器
view.__name__ = name
view.__module__ = cls.__module__
# 每次循环取出一个装饰器
for decorator in cls.decorators:
# 本质就是把被装饰的函数当做参数传到装饰器,把返回结果赋值给被装饰的函数
view = decorator(view)
view.__name__ = name
return view
# MethodView的self.dispatch_request方法
def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue:
# request.method.lower()是请求方式的小写
# meth 是cbv中与请求方式同名的方法
meth = getattr(self, request.method.lower(), None)
return current_app.ensure_sync(meth)(**kwargs)
# 本质就是执行cbv中与请求方式同名的方法
5.为什么 decorators = [auth] 能加装饰器
# app.add_url_rule('/home', view_func=Home.as_view('home'))
app.add_url_rule('/home', view_func=Home.view的内存地址)
# 用装饰器一直在装饰view的内存地址,所以后续的执行是有装饰器的view
@auth
def view(**kwargs):
return self.dispatch_request(**kwargs)
等价于
view = auth(view)
6.endpiont
view_func=Home.as_view('home')
home 是 endpoint,就是路由别名
-1 app.add_url_rule('/home', view_func=Home.as_view('home'))
-2 add_url_rule---》endpoint没传---》会执行endpoint = _endpoint_from_view_func(view_func)
-3 取函数名作为 endpoint 的值
-4 view_func是 加了一堆装饰器的view函数---》它的名字应该是装饰器的名字--》但是
view.__name__ = name # name 就是home
-5 所以endpoint就是你传的home
-6 如果传了endpoint,就是传的那个,那as_view('home')就没作用了,但是也必须要传