国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

flask route設(shè)計(jì)思路

vvpale / 2907人閱讀

摘要:引言本文主要梳理了源碼中的設(shè)計(jì)思路。協(xié)議將處理請(qǐng)求的組件按照功能及調(diào)用關(guān)系分成了三種。不論是什么,最終都會(huì)調(diào)用函數(shù)。

引言

本文主要梳理了flask源碼中route的設(shè)計(jì)思路。
首先,從WSGI協(xié)議的角度介紹flask route的作用;
其次,詳細(xì)講解如何借助werkzeug庫(kù)的MapRule實(shí)現(xiàn)route
最后,梳理了一次完整的http請(qǐng)求中route的完整流程。

flask route 設(shè)計(jì)思路 源碼版本說(shuō)明

本文參考的是flask 0.5版本的代碼。
flask 0.1版本的代碼非常短,只有600多行,但是這個(gè)版本缺少blueprint機(jī)制。
因此,我參考的是0.5版本。

flask route示例

直接使用flask官方文檔中的例子

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello_world():
    return "Hello World!"
    
@app.route("/post/")
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return "Post %d" % post_id

if __name__ == "__main__":
    app.run()

此例中,使用app.route裝飾器,完成了以下兩個(gè)url與處理函數(shù)的route:

{ 
    "/": hello_world, 
    "/post/" : show_post
}

這樣做的效果為:
當(dāng)http請(qǐng)求的url為"/"時(shí),flask會(huì)調(diào)用hello_world函數(shù);
當(dāng)http請(qǐng)求的url為"/post/<某整數(shù)值>"(例如/post/32)時(shí),flask會(huì)調(diào)用show_post函數(shù);

flask route的作用

從上面的示例中其實(shí)可以明白:flask route的作用就是建立url與處理函數(shù)的映射

WSGI協(xié)議將處理請(qǐng)求的組件按照功能及調(diào)用關(guān)系分成了三種:server, middleware, application
其中,server可以調(diào)用middleware和application,middleware可以調(diào)用application。

符合WSGI的框架對(duì)于一次http請(qǐng)求的完整處理過(guò)程為:
server讀取解析請(qǐng)求,生成environ和start_response,然后調(diào)用middleware;
middleware完成自己的處理部分后,可以繼續(xù)調(diào)用下一個(gè)middleware或application,形成一個(gè)完整的請(qǐng)求鏈;
application位于請(qǐng)求鏈的最后一級(jí),其作用就是生成最終的響應(yīng)。

 http服務(wù)器(比如,nginx)--> WSGI server(比如gunicorn,SimpleHttpServer)-->middleware-->
 middleware--> ... -->application

如果接觸過(guò)Java Web 開發(fā)的人可能會(huì)立刻發(fā)現(xiàn),這與servlet中的middleware機(jī)制是完全一致的。

特別重要的:

在上一小節(jié)的示例中app = Flask(__name__)創(chuàng)建了一個(gè)middleware
而這個(gè)middleware的核心作用是進(jìn)行請(qǐng)求轉(zhuǎn)發(fā)(request dispatch)。

上面這句話非常重要,請(qǐng)?jiān)谛睦镏貜?fù)一百遍。
上面這句話非常重要,請(qǐng)?jiān)谛睦镏貜?fù)一百遍。
上面這句話非常重要,請(qǐng)?jiān)谛睦镏貜?fù)一百遍。

進(jìn)行請(qǐng)求轉(zhuǎn)發(fā)的前提就是能夠建立url與處理函數(shù)之間的映射關(guān)系,即route功能。
因此,在flask中,route是Flask類的一個(gè)裝飾器。

flask route的實(shí)現(xiàn)思路

通過(guò)上一小節(jié),我們知道以下兩點(diǎn):

flask route 是url與處理函數(shù)的映射關(guān)系;

在http請(qǐng)求時(shí),Flask這個(gè)middleware負(fù)責(zé)完成對(duì)url對(duì)應(yīng)的處理函數(shù)的調(diào)用;

那么,如果是我們自己來(lái)實(shí)現(xiàn)route,思路也很簡(jiǎn)單:

建立一個(gè)類Flask,這個(gè)類是一個(gè)middleware,并且有一個(gè)字典型的成員變量url_map

url_map = {url : function}

當(dāng)http請(qǐng)求時(shí),進(jìn)行request dispatch:根據(jù)url,從url_map中找到function,然后調(diào)用function;

調(diào)用后續(xù)的middleware或application,并把function的結(jié)果傳遞下去。

flask的實(shí)現(xiàn)思路也是這樣的。

class Flask(object):

    def __init__(self):
        self.url_map = {}  # 此處定義保存url與處理函數(shù)的映射關(guān)系
        
    def __call__(self, environ, start_response):  # 根據(jù)WSGI協(xié)議,middleware必須是可調(diào)用對(duì)象
        self.dispatch_request()    # Flask的核心功能 request dispatch
        return application(environ, start_response)  #最后調(diào)用下一級(jí)的application
    
    def route(self, rule):  # Flask使用裝飾器來(lái)完成url與處理函數(shù)的映射關(guān)系建立
        def decorator(f):   # 簡(jiǎn)單,侵入小,優(yōu)雅
            self.url_map[rule] = f
            return f
        return decorator
    
    def dispath_request(self):
        url = get_url_from_environ() #解析environ獲得url 
        return self.url_map[url]() #從url_map中找到對(duì)應(yīng)的處理函數(shù),并調(diào)用

至此, 一個(gè)簡(jiǎn)單的Flaskmiddleware的骨架就完成了。
上面的Flask類主要功能包括:

符合WSGI協(xié)議的middleware:可被調(diào)用,并且可以調(diào)用application

能夠保存url與處理函數(shù)的映射信息

能夠根據(jù)url找到處理函數(shù)并調(diào)用(即,request dispatch)

當(dāng)然,在實(shí)際中,不可能這么簡(jiǎn)單,但是基本思路是一致的。

werkzeug庫(kù)中的Map與Rule在Flask中的應(yīng)用

需要指出,上面實(shí)現(xiàn)的最簡(jiǎn)單的Flask類還是有很多問題的。
比如,HTTP請(qǐng)求中相同的url,不同的請(qǐng)求方法,比如GET,POST如果對(duì)應(yīng)不同的處理函數(shù),該如何處理?

flask使用了werkzeug庫(kù)中的MapRule來(lái)管理url與處理函數(shù)映射關(guān)系。

首先需要簡(jiǎn)單了解一下MapRule的作用:
werkzeug中,Rule的主要作用是保存了一組urlendpointmethods關(guān)系:
每個(gè)(url, endpoint, methods)都有一個(gè)對(duì)應(yīng)的Rule對(duì)象:
其實(shí)現(xiàn)如下:

class Rule(object):
    def __init__(self, url, endpoint, methods):
        self.rule = url
        self.endpoint = endpoint
        self.methods = methods

這里需要解釋一下endpoint
前面說(shuō)過(guò):url與其處理函數(shù)可以使用一個(gè)字典來(lái)實(shí)現(xiàn):{url: function}

flask在實(shí)現(xiàn)的時(shí)候,在中間加了一個(gè)中介endpoint,于是,url與處理函數(shù)的映射變成了這樣:

url-->endpoint-->function #一個(gè)url對(duì)應(yīng)一個(gè)endpoint,一個(gè)endpoint對(duì)應(yīng)一個(gè)function
{url: endpoint} # 保存url與endpoint之間的關(guān)系
{endpoint: function} #保存endpoint與function之間的關(guān)系

于是,剛才我們實(shí)現(xiàn)的簡(jiǎn)單的flask骨架中{url: function}的字典,就變成了{endpoint: function}
{url: endpoint}這個(gè)映射關(guān)系就需要借助MapRule這兩個(gè)類來(lái)完成。

可以發(fā)現(xiàn):endpoint就是url和處理函數(shù)映射關(guān)系中的一個(gè)中介,所以,它可以是任何可以用作字典鍵的值,比如字符串。
但是在實(shí)際使用中endpoint,一般endpoint均為字符串,并且默認(rèn)情況下:

如果是通過(guò)Flask.route裝飾器建立的映射關(guān)系,那么endpoint就是處理函數(shù)的函數(shù)名;

如果是通過(guò)blueprint建立的映射關(guān)系,那么endpoint是blueprint名.處理函數(shù)名;

因?yàn)椋拷⒁粋€(gè)url-->endpoint-->function關(guān)系就會(huì)創(chuàng)建一個(gè)Rule對(duì)象,所以,會(huì)有很多Rule對(duì)象存在。
Map的作用則是保存所有Rule對(duì)象。
所以,一般情況下Map的用法如下:

    m = Map([
            Rule("/", endpoint="index"),
            Rule("/downloads/", endpoint="downloads/index"),
            Rule("/downloads/", endpoint="downloads/show")
           ])

在flask的源碼中

class Flask(object):
    def __init__(self):
        self.url_map = Map()  # url_map為保存所有Rule關(guān)系的容器Map
        self.view_functions = {} # view_functions保存endpoint-->function

成員變量url_map保存所有的(url, endpoint, method)關(guān)系

成員變量view_functions保存所有的{endpoint, function}關(guān)系

所以,對(duì)于一個(gè)url,只要能找到(url,endpoint,method),就能根據(jù)endpoint找到對(duì)應(yīng)的function

route的完整流程

首先,建立Flask對(duì)象:

app = Flask(__name__)

然后,建立urlfunction之間的映射關(guān)系:

@app.route("/")
def hello_world():
    return "Hello World!"

在裝飾器route中,創(chuàng)建(url, endpoint, method){endpoint: function}兩組映射關(guān)系:

if endpoint is None:
    endpoint = view_func.__name__ # 默認(rèn)使用響應(yīng)函數(shù)名作為endpoint
self.url_map.add(Rule(url, endpoint, method)) # 保存(url, endpoint, method)映射關(guān)系
self.view_functions[endpoint] = view_func  # 保存{endpoint: function}映射關(guān)系

這樣,就完成了對(duì)url和響應(yīng)函數(shù)的映射關(guān)系。

下一步,調(diào)用WSGI server響應(yīng)http請(qǐng)求,在文章開始的示例中使用:

app.run()

調(diào)用python標(biāo)準(zhǔn)庫(kù)提供的WSGI server,在實(shí)際使用時(shí),可能是gunicornuwsgi

不論server是什么,最終都會(huì)調(diào)用Flask.__call__函數(shù)。這個(gè)函數(shù)完成request dispatch的任務(wù)。

對(duì)于request dispatch而言,首先根據(jù)請(qǐng)求,解析environ,得到url,
然后調(diào)用Map.match函數(shù),這個(gè)函數(shù)會(huì)最終找到預(yù)先保存的(url, endpoint, method)映射,
然后返回(endpoint, url請(qǐng)求參數(shù)),
由于得到了endpoint,然后,可以從Flask.view_functions中直接取到對(duì)應(yīng)的響應(yīng)函數(shù),
所以,可以直接進(jìn)行函數(shù)調(diào)用

self.view_functions[endpoint](url請(qǐng)求參數(shù))

至此,就完成了完整的route

總結(jié)

flaskFlask類是WSGIdispatch middleware

Flaskurl_map保存所有的(url, endpoint, method)映射關(guān)系;

Flaskview_functions保存所有的{endpoint: function}映射關(guān)系;

dispath request就是根據(jù)url找到endpoint,再根據(jù)endpoint找到function,最后調(diào)用function的過(guò)程

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/37690.html

相關(guān)文章

  • flask route對(duì)協(xié)議作用及設(shè)計(jì)思路解答

      小編寫這篇文章的一個(gè)主要目的,主要是給大家講解一下flask route,講解的內(nèi)容是flask route協(xié)議的一些相關(guān)作用,還有具體的一些設(shè)計(jì)思路,具體的思路性問題,下面去給大家做一個(gè)詳細(xì)解答。  引言  本文主要梳理了flask源碼中route的設(shè)計(jì)思路。  首先,從WSGI協(xié)議的角度介紹flask route的作用;  其次,詳細(xì)講解如何借助werkzeug庫(kù)的Map、Rule實(shí)現(xiàn)ro...

    89542767 評(píng)論0 收藏0
  • python 最快 web 框架 Sanci 快速入門

    摘要:詳細(xì)信息可以看下這個(gè)問題先在說(shuō)下我的部署方式使用部署配置文件啟動(dòng)方式總結(jié)試用了下,把之前的一個(gè)聊天機(jī)器人從改成了。預(yù)告下一篇將介紹如何使用一步一步創(chuàng)建一個(gè)聊天機(jī)器人。 簡(jiǎn)介 Sanic 是一個(gè)和類Flask 的基于Python3.5+的web框架,它編寫的代碼速度特別快。除了像Flask 以外,Sanic 還支持以異步請(qǐng)求的方式處理請(qǐng)求。這意味著你可以使用新的 async/await ...

    snifes 評(píng)論0 收藏0
  • [貳]Flask web開發(fā):程序的基本結(jié)構(gòu)

    摘要:本篇對(duì)應(yīng)書本第二章程序的基本結(jié)構(gòu)。初始化導(dǎo)入模塊創(chuàng)建類的實(shí)例注對(duì)于開發(fā)者來(lái)說(shuō),傳給應(yīng)用程序構(gòu)造函數(shù)的參數(shù)是比較容易弄混淆的。不同的請(qǐng)求方法發(fā)送到相同的上時(shí),會(huì)使用不同的視圖函數(shù)進(jìn)行處理。 本系列筆記是我閱讀Miguel Grinberg的《Flask Web Development》的筆記,標(biāo)題與書本同步。希望通過(guò)記錄技術(shù)筆記的方式促進(jìn)自己對(duì)知識(shí)的理解。 本篇對(duì)應(yīng)書本第二章:程序的基本...

    maxmin 評(píng)論0 收藏0
  • Flask框架基礎(chǔ)(二)

    摘要:處理和函數(shù)之間關(guān)系的程序稱為路由。模板引擎是由實(shí)現(xiàn)的是內(nèi)置的模板語(yǔ)言參照設(shè)計(jì)思想設(shè)計(jì)的,跟差不多渲染模板默認(rèn)情況下,在程序文件夾中的子文件夾中尋找模板。如果需要可在文件夾中使用子文件夾存放文件。 1 程序的基本結(jié)構(gòu) 1.1初始化 所有Flask 程序都必須創(chuàng)建一個(gè)程序?qū)嵗eb 服務(wù)器使用一種名為Web 服務(wù)器網(wǎng)關(guān)接口(Web Server Gateway Interface,WSG...

    lpjustdoit 評(píng)論0 收藏0
  • python10min手寫一個(gè)服務(wù)器內(nèi)存監(jiān)控系統(tǒng)

    簡(jiǎn)易的內(nèi)存監(jiān)控系統(tǒng) 本文需要有一定的python和前端基礎(chǔ),如果沒基礎(chǔ)的,請(qǐng)關(guān)注我后續(xù)的基礎(chǔ)教程系列博客 文章源地址,還可以看到具體的代碼,喜歡請(qǐng)加個(gè)星星 騰訊視頻鏈接 錄制中間網(wǎng)出問題了,重啟了一下,所以有兩部分 視頻1 視頻2 本文的目的在于,盡可能用簡(jiǎn)單的代碼,讓大家了解內(nèi)存監(jiān)控的原理主題思路 獲取內(nèi)存信息 存儲(chǔ)信息 展現(xiàn) 后續(xù)擴(kuò)展 加主機(jī)名,monitor部署在多臺(tái)機(jī)器,不直接插...

    sunsmell 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<