理解@app.route()


 

from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run() 

我覺得只要稍微看過 Flask 官方教程的小伙伴都會對這個代碼很熟悉,熟悉歸熟悉,那小伙伴們理解 **@app.route()**是如何發揮作用的嗎?如果不清楚的話,嗯哼,just follow me~~

在理解這個之前,我們需要做一些准備。

@app.route 和 裝飾器

為了理解 @app.route() 是如何發揮作用的,我們首先需要對 Python 中的裝飾器有個大體的認識。具體的可以參考廖老師的教程--裝飾器。老實說,裝飾器其實就是在一個函數內部定義另外一個函數,然后返回一個新的函數,即動態的給一個對象添加額外的職責。如果還不是很明白的話,沒關系,我們來看看具體的例子。

def simple_decorator(f): def wrapper(): print "func enter" f() print "func exit" return wrapper @simple_decorator def hello(): print "Hello World!" hello() 

運行一下上述代碼,我們將會看到如下的輸出:

 

看完這個例子,小伙伴們有沒有稍微理解一點 @app.route() 了呢?可能有的小伙伴會說,@app.route() 是帶參的,我們的裝飾器並沒有任何參數,這個很簡單,接下來讓我們試着,讓我們的裝飾器也可以傳遞參數。

def not_very_simply_decorator(enter_msg,exit_msg): def simple_decorator(f): def wrapper(): print enter_msg f() print exit_msg return wrapper return simple_decorator @not_very_simply_decorator("func enter","func exit") def hello(): print "Hello World" hello()

是不是很奇怪,我為啥讓兩次的輸出信息都一樣,因為那樣子,我只需要截一次圖了~~哈哈,有沒有覺得這個跟 app.route() 越來越有點像了,有的小伙伴肯定要說了,人家是 app.route(),而我的是 func(),那我只能說,咱們再接着往下看。

從 route() 到 app.route()的不歸路

在此之前,如果有小伙伴跟我一樣用 Pycharm 的話,使用它直接創建一個 Flask 項目,然后去點擊 app.route()的話,會發現它跳轉到了一個 Flask.py 的文件內,這個文件內容是一個 Flask 對象,而我們的 route() 函數就在其中,為了更好的理解 Flask 對象,我們可以嘗試模仿它,創建一個類似的 Flask 對象。

class FlaskBother():
    def route(self,route_str):
        def decorator(f):
            return f
        return decorator

app = FlaskBother()

@app.route('/')
def hello():
    return 'Hello World'

看到這里,我就問一句,像不像?這個和我們之前創建的裝飾器的主要區別在於,我們不想去修改我們裝飾的這個函數的功能,我們只想去引用它,so 重點來了,聰明的你們知道,我們需要什么嗎~~我們需要一個變量去存儲路由和其關聯的函數。那么 Flask 有沒有這個變量呢,答案是肯定的,那我們如何在 Flask 中去查看所有的路由,以最初的最小的 Flask 為例。

進入Python交互模式

>>> from Hello import app

>>> app.url_map

Map([<Rule '/' (HEAD, OPTIONS, GET) -> hello>, <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>]) 

好了說完在 Flask 中如何查看所有路由,為了在我們的 FlaskBother實現同樣的功能,我們添加一個 "route" 字典到我們 FlaskBother 對象中。當我們的裝飾器被調用的時候,我們將路由和關聯的函數保存到我們的 "route" 字典中去。

class FlaskBother():
    def __init__(self):
        self.routes = {}
    def route(self,route_str):
        def decorator(f):
            self.routes[route_str] = f
            return f
        return decorator

app = FlaskBother()

@app.route("/")
def hello()
    return "Hello World"

其實到這里我們基本上已經完成了百分之90%了,我們現在唯一欠缺是一個可以訪問內部 route 的途徑,所以讓我們再添加一個函數 server(path),通過這個函數我們可以通過路由去訪問其關聯的函數,如果沒有的話,自然返回一個錯誤。

class FlaskBother(): def __init__(self): self.routes = {} def route(self,route_str): def decorator(f): self.routes[route_str] = f return f return decorator def server(self,path): view_function = self.routes.get(path) if view_function: return view_function() else: raise ValueError('Route "{}" has not been registered'.format(path)) 

這就算完了嗎?並沒有,讓我們嘗試運行下面的程序:

app = FlaskBohter()
@app.route("/")
def hello():
    return "Hello World"

print app.server("/")

 

到這里不知道小伙伴們對 @app.route() 有沒有一點理解~~如果還沒有理解的話,不要急,我們慢慢來,如何將server(path) 掛載到 HTTP 服務器這里就不說了~~好了,小伙伴們下次見~~

歡迎小伙伴們掃碼我的頭像,關注我的微信號~我是桃子,和有趣的桃子用Python做有趣的事情。

編輯於 2018-09-15


免責聲明!

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



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