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 跟之前一样