flask之cbv、模版
一、CBV介绍
1、class-based views, CBVs
通常使用函数视图(function-based views, FBVs)来定义路由和处理逻辑。不过,Flask 也支持基于类的视图(class-based views, CBVs),这可以帮助在需要共享逻辑或管理复杂视图结构时组织代码。
基于类的视图 CBV 的特点
- 组织性:CBV 方式可以更好地组织和重用代码,尤其适用于复杂的视图逻辑。
- 可继承性:可以通过类继承的方式实现逻辑的共享和复用。
- 封装性:通过类的方法封装不同的 HTTP 请求方法(如 GET、POST、PUT 等)逻辑。
2、类要继承MethodView
CBV 的基本方式是通过继承 flask.views.MethodView。
from flask import Flask, request, jsonify, url_for
from flask.views import MethodView
app = Flask(__name__)
class MyView(MethodView):
def get(self):
return jsonify({"message": "This is a GET request"})
def post(self):
data = request.get_json()
print(url_for("my_view"))
return jsonify({"message": "This is a POST request", "data": data})
# 注册路由,绑定视图类
app.add_url_rule('/myview', view_func=MyView.as_view('my_view'))
if __name__ == '__main__':
app.run(debug=True)
补充:
指定方法名称:
在基于类的视图中,HTTP 方法名 get, post, delete 应该直接作为方法名。Flask 自动根据请求的 HTTP 方法调用相应的类方法。因此,需要定义 get, post, delete 方法,而不是 mesg1, mesg2 等自定义方法名称。
也可以显式声明 methods 属性, 如果显式声明了,不在声明中的方法将不被允许
class MyView(MethodView):
methods = ['get', 'post']
def get(self):
return jsonify({"message": "This is a GET request"})
def post(self):
data = request.get_json()
print(url_for("my_view"))
return jsonify({"message": "This is a POST request", "data": data})
3、路由的别名
view_func=MyView.as_view
def post(self):
data = request.get_json()
print(url_for("my_view"))
return jsonify({"message": "This is a POST request", "data": data})
通过url_for反向解析路由,MyView.as_view 括号中的内容my_view 是myview的别名
即myview怎么修改name,都可以通过别名my_view 去解析到

4、cbv加装饰器
# 定义一个简单的认证装饰器
def api_key_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if request.headers.get("API-Key") != "my-secret-key":
return jsonify({"error": "Unauthorized"}), 401
return f(*args, **kwargs)
return decorated_function
# 全局装饰器,decorators = [xxx]
class MyView(MethodView):
decorators = [api_key_required]
def get(self):
return jsonify({"message": "This is a GET request"})
def post(self):
data = request.get_json()
return jsonify({"message": "This is a POST request", "data": data})
# 局部装饰 写在类中方法上
class MyView(MethodView):
def get(self):
return jsonify({"message": "This is a GET request"})
@api_key_required
def post(self):
data = request.get_json()
return jsonify({"message": "This is a POST request", "data": data})
5、cbv 源码分析
MethodView继承了View,View中有as_view方法---> 本质是执行了dispath_request---->View没有写 dipatch(空的内容)---> MethodView写了所以,视图类必须要继承MethodView
1 请求来了,路由匹配成功---》执行ItemAPI.as_view('item')()--->view加括号执行
2 ItemAPI.as_view('item')执行结果:就是View中as_view方法中的闭包函数 view
3 view()--->执行self.dispatch_request()---》执行MethodView的dispatch_request
def dispatch_request(self, **kwargs):
meth = getattr(self, request.method.lower(), None)
return meth(**kwargs)
4 如果是get请求,就会执行视图类中的get方法
class View:
@classmethod
def as_view()
def view():
self.dispatch_request()
return view
6、endpoint 的使用
app.add_url_rule('/item', endpoint='xxx',view_func=ItemAPI.as_view('item'))
如果写了endpoint---> 别名以它为准,如果不写以 as_view的参数为准
## 逻辑:
1 app.add_url_rule('/item',endpoint='xxx', view_func=ItemAPI.as_view('item'))
2 endpoint = _endpoint_from_view_func(view_func)
如果endpoint没传,就会走这句
view_func 是 ItemAPI.as_view('item') 它就是 view
3 _endpoint_from_view_func(view_func)---》返回了传入的函数的名字
return view_func.__name__
4 如果上面传入了ItemAPI.as_view('item'),它的函数名就是view---》endpoint就是view
## 总结:
endpoint如果不传,会以视图函数的函数名作为endpoint
-fbv:如果不写endpoint,会以函数名作为endpoint,但是如果多个视图函数加了同一个装饰器,又没有指定endpoint,就会出错了
-cbv:调用as_view一定要传入一个字符串---》如果endpoint没写,endpoint就是传入的这个字符串,如果写了,这个字符串没用
如果传了,直接以endpoint传入的作为endpoint
二、模版(前端使用的模版)
1、flask使用了Jinja模版
flask提供了文档,也可以去Jinja官网看
https://flask.palletsprojects.com/en/3.0.x/
https://jinja.palletsprojects.com/en/3.1.x/
# 总结:之前学过dtl
-{{变量/简单表达式/函数}}
-{%if/for %} {%endif%} {%endfor%}
-比dtl强大 ,Jinja中可以加括号
-字典取值,列表取值跟python语言一样,之前dtl 通过 .取值
-过滤器,标签
-extends,include 跟之前一样

浙公网安备 33010602011771号