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 方法名 getpostdelete 应该直接作为方法名。Flask 自动根据请求的 HTTP 方法调用相应的类方法。因此,需要定义 getpostdelete 方法,而不是 mesg1mesg2 等自定义方法名称。

也可以显式声明 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 跟之前一样

  

 

posted @ 2024-10-31 11:32  凡人半睁眼  阅读(4)  评论(0编辑  收藏  举报