Flask-3-視圖(可插拔視圖)


前沿:本次分享主要是基於類的視圖

一、什么是視圖函數?

簡單來說,被url裝飾的==>后面處理邏輯的方法就是視圖函數,一般制作三件事,接收請求參數,數據處理邏輯、構建響應對象對並返回

一般來說視圖函數內的邏輯不應該過長,具體邏輯在另外的模塊去封裝,等封裝的盡量盡快封裝,不要等以后,以后重構的話更麻煩更累。

二、視圖函數的形式

1、分請求方法

路由中可以根據不同的請求方法來返回不同的東西
比如: project 如果是get請求就返回project信息
如果是post請求 就新增一個project

2、分請求單復數

路由中可以根據參數來動態決定響應對象,例如 project 接口 如果傳了id,就返回對象id,的項目信息,如果沒有穿則返回全部項目信息,可以定義一個默認id值,defaults = {"id":None}

3、注意視圖函數對應MVC的部分,不要越界

視圖函數應該負責哪一塊已經反復強調幾次,不在重復

4、注意:

上述說的視圖形式,只是一種舉例,具體怎么使用,完全靠自己習慣,你要寫兩個視圖函數來實現,一個視圖函數只做一件事情。這種也是完全OK的。遵循RESTFUL那一套也是很好,不過對於前端后不分離,我還是喜歡寫一個視圖中,這樣處理會省事些。

三、基於類的視圖(也可以叫可插拔視圖)

1、什么是基於類的視圖?

falsk從Django那學來,以類的方式實現視圖函數的邏輯,封裝get,post函數,如果請求方法是get就掉用類中get函數,如果是post請求,就掉類中post的函數,根據請求方法來和類中的函數弄一個綁定關系,達到這種映射的效果,不過需要繼承flask的View類。

2、類視圖有什么好處

  • 類是可以繼承的
  • 代碼可以復用
  • 可以定義多中行為
  • 上述說了一個視圖實現多個功能的,邏輯就很多 ,此時我們用基於類的視圖則比較優雅

3、可插拔視圖案例

  • 需要繼承View
  • 必須重寫dispatch_request方法,主要實現請求調度的作用。
  • 請求方法的限制,可以放在類的methods屬性定義
  • 裝飾器也可以使用自定義裝飾器,用decorators屬性定義
  • 類視圖寫完我,不能用flask的app.route裝飾器來注冊路由,只能用add_url_rule方法,綁定視圖時用as_view()意思是將類轉成視圖函數用,接收一個name參數,定義視圖函數的名字,或者說定義端點名。因為端點默認取的就是視圖函數的名字
  • View類中都有說明,可參考VIew源碼
from flask.views import View
from flask import Flask, request


# 基於類的視圖
class Project(View):
    # 定義請求方法
    methods = ["GET", "POST"]
    
    # get請求方法的執行邏輯
    def get(self):
        return "get"
    
    # post請求方法執行的邏輯
    def post(self):
        return "post"
    
    # 調度函數,必須重寫。不重寫,View類會直接拋異常
    def dispatch_request(self):
        # 請求方法映射關系
        request_method = {"get": self.get, "post": self.post}
        # 通過requset方法獲取前端訪問的請求方法
        print(request.method)
        # 通過請求方法,映射到對應的函數對象
        view = request_method.get(request.method.lower())
        print(view)
        # 返回映射到的函數返回值
        return view()


app = Flask(__name__)
# 只能采用集中注冊,用as_view方法
app.add_url_rule("/project", view_func=Project.as_view("project"))

# 可以打印看一下視圖和url的綁定關系
print(app.url_map)

if __name__ == '__main__':
    app.run(debug=True)

四、來自Flask的優化MethodView類。

上述我們自己些調度函數dispatch_request,屬於硬編碼,這種映射關系是我們寫死的。非常不優雅。而falsk給我們另外基於View類封裝一個MethodView,它里面幫我用獲取類屬性的方式,也就是用getattr的方法,更加優化的重寫了View類的dispatch_request方法

說這么多,所以呢?有什么用?

只要我們的類視圖繼承這個MethodView類,我們就不需要在每個類視圖中在重寫dispatch_request。完全不需要在寫這個方法了,除非你還有別的要擴展可以超繼承或者重寫都行

from flask.views import View, MethodView
from flask import Flask, request


class Project(MethodView):
    methods = ["GET", "POST"]

    def get(self,project_id=None):
        if project_id is None
            return "所有項目"
        return "單個項目"

    def post(self):
        return "post"
    
    # 注釋掉也是一樣的效果,不需要在寫了
    # def dispatch_request(self):
    #     request_method = {"get": self.get, "post": self.post}
    #     print(request.method)
    #     view = request_method.get(request.method.lower())
    #     print(view)
    #     return view()


app = Flask(__name__)
app.add_url_rule("/project/<project>", view_func=Project.as_view("project"),methods=["GET"])
print(app.url_map)

if __name__ == '__main__':
    app.run(debug=True)

五、類視圖實現不同功能是的注冊機制

類視圖非常適合對同一個范疇的東西,不同的功能實現,如項目操作,查詢單個項目、查詢所有項目、創建項目、刪除項目、更新項目等等,此時我們一個類視圖就都能實現了,但是在注冊的時候 需要分開注冊成不同的路由。

from flask.views import View, MethodView
from flask import Flask, request


class Project(MethodView):

    def get(self, project_id=None):
        if project_id is None:
            return "所有項目"
        return "單個項目"

    def post(self):
        return "創建項目"

    def delete(self,project_id):
        return "刪除項目"


app = Flask(__name__)
view_func = Project.as_view("project")
# 類視圖實現多個功能,我們要集中也建立多個路由,對處理
# 獲取單個項目,或刪除
app.add_url_rule("/project/<int:project_id>", view_func=view_func, methods=["GET","DELETE"])
# 獲取所有項目
app.add_url_rule("/projects", view_func=view_func, methods=["GET"])
# 創建項目
app.add_url_rule("/project/create", view_func=view_func, methods=["POST"])
print(app.url_map)

if __name__ == '__main__':
    app.run(debug=True)

基於MethedVeiew,采用TESTFUL的設計思路

URL 方法 功能說明
/projects/ GET 獲取項目列表
/projects/ POST 創建一個項目
/projects/ GET 獲取一個項目
/projects/ PUT 更新一個項目
/projects/ delete 刪除一個項目
.... ..... ....

傳統的視圖函數(前端后不分離的情況)

我們通常會在函數加很多if判斷

@app.route("/projects/<project_id>", methods=["GET", "POST", "PUT", "DELETE"])
def project(project_id):
    method = request.method
    if method == "GET":
        return f"get {project_id}"
    elif method == "post":
        return f"post {project_id}"
    # .....
    return "其他的方法判斷"

六、總結:

  • 基於類的視圖,能夠比較優雅的方式實現很多復雜的不同功能
  • 類視圖定義請求方法,需要加類屬性:methods = ['GET']
  • 要明白類視圖其中是怎么通過請求方法,調度的,核心是基於dispatch_request方法調度的
  • 不能用@app.route()注冊
  • 只能用app.add_url_rule("url",類對象.as_view(視圖名字/端點名))
  • as_view 最后就是調用dispatch_request方法。
  • 類視圖用裝飾器時,不能在類和類方法上直接裝飾,因為我們要裝飾的是視圖函數(也就是最后執行的是調度類函數),View類中幫我們定義了一個增加裝飾器的方法,定義類屬性 decorators = [裝飾器函數名]
  • 說明:view和methodView源碼就不貼出來了,想了解可以自己導入后查看,注釋寫的非常明白,也都有案例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM