Flask框架從入門到精通之轉換器(四)

〆 小源。發表於2019-04-19

知識點:
1、轉換器
2、自定義轉換器
3、轉化器高階用法

一、概況

有很多請求我們URL地址後面會跟著引數,並且後端要提取到引數,比如:http://127.0.0.1:5000/center/1這個URL地址後面有個1,可以代表我們要訪問uid為1的個人資訊。那麼我們如何提取到引數呢?這個時候就會用到Flask的轉換器。

二、轉換器

Flask中支援下面這些轉換器:

轉換器 含義
int 接受整數
float 同 int ,但是接受浮點數
path 和預設的相似,但也接受斜線
from flask import Flask
from flask import abort, redirect, url_for

app = Flask(__name__)


@app.route('/center/<int:uid>')  # 代表個人中心頁
def center(uid):  # 檢視函式

    return 'your uid %s' % uid  # 返回內容


if __name__ == '__main__':
    # 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
    app.run(host='0.0.0.0', port=5000)  # 執行程式

複製程式碼

在瀏覽器訪問:

在這裡插入圖片描述
如果改成:

@app.route('/center/<float:uid>')  # 代表個人中心頁
複製程式碼

再去訪問就會報錯,因為float只支援浮點數。

在這裡插入圖片描述
如果不寫轉換器,那麼它的預設轉換器就是str型別。但是不包含/,因為它在這裡面有特殊的意義。

@app.route('/center/<uid>')  # 代表個人中心頁
複製程式碼

在這裡插入圖片描述
如果要匹配/,請用path轉換器:

@app.route('/center/<path:uid>')  # 代表個人中心頁
複製程式碼

在這裡插入圖片描述

三、自定義轉換器

有時候系統提供的轉換器並不能滿足我們,比如我們需要的UID是至少5最多10位。如果不是這個範圍呢,我們就可以認為不滿足我們的匹配規則。而現在我們不管輸入多少位,後臺都會匹配上,然後就去執行我們的檢視。如果要排除這種現象,我們就需要自定義轉換器。

需要用到Flask這個轉換器基類BaseConverter

from flask import Flask
from flask import abort, redirect, url_for
from werkzeug.routing import BaseConverter

app = Flask(__name__)


# 自定義轉換器
class MyConverter(BaseConverter):

    def __init__(self, map):
        super().__init__(map)  # 呼叫父類
        self.regex = r'\d{5,10}'  # 轉換器的正則規則


app.url_map.converters['re'] = MyConverter  # 註冊到converters

#會根據註冊的鍵re找到MyConverter這個類建立物件
@app.route('/center/<re:uid>')  # 代表個人中心頁
def center(uid):  # 檢視函式

    return 'your uid %s' % uid  # 返回內容


if __name__ == '__main__':
    # 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
    app.run(host='0.0.0.0', port=5000)  # 執行程式

複製程式碼

這個在瀏覽器試下:

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
我們發現已經完全解決了我們剛才的問題。

四、優化轉換器

我們發現這個轉化器的規則是寫死的,只能匹配UID,如果其他地方用到要匹配手機號怎麼辦,所以最好匹配規則是動態傳遞的。那麼改成如下:

from flask import Flask
from flask import abort, redirect, url_for
from werkzeug.routing import BaseConverter

app = Flask(__name__)


# 自定義轉換器
class MyConverter(BaseConverter):

    def __init__(self, map, re):
        super().__init__(map)  # 呼叫父類
        self.regex = re  # 轉換器的正則規則


app.url_map.converters['re'] = MyConverter  # 註冊到converters


#會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/center/<re(r"\d{5,10}"):uid>')  # 代表個人中心頁
def center(uid):  # 檢視函式

    return 'your uid %s' % uid  # 返回內容


@app.route('/login/<re(r"1[3456789]\d{9}"):phone>')  # 代表登入頁
def login(phone):  # 檢視函式

    return 'your phone %s' % phone  # 返回內容


if __name__ == '__main__':
    # 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
    app.run(host='0.0.0.0', port=5000)  # 執行程式

複製程式碼

用到的時候,在把具體的正則條件傳遞進去,就好了。

五、轉換器高階用法

通過上面的一些場景我們用到了轉換器,可是既然轉換器,我們並沒有看出轉換這個兩個字在哪有體現,感覺不如叫介面卡。但是進入BaseConverter原始碼裡面看一下,發現有兩個方法,這兩個方法是到底有什麼作用呢,不妨我們來重寫一下。

class BaseConverter(object):

    """Base class for all converters."""
    regex = '[^/]+'
    weight = 100

    def __init__(self, map):
        self.map = map

    def to_python(self, value):
        return value

    def to_url(self, value):
        return url_quote(value, charset=self.map.charset)
複製程式碼
  • 重寫to_python 我們在這個方法裡面隨便返回點內容
from flask import Flask
from flask import abort, redirect, url_for
from werkzeug.routing import BaseConverter

app = Flask(__name__)


# 自定義轉換器
class MyConverter(BaseConverter):

    def __init__(self, map, re):
        super().__init__(map)  # 呼叫父類
        self.regex = re  # 轉換器的正則規則

    def to_python(self, value):
        return '呵呵'  # 隨便給一個返回值


app.url_map.converters['re'] = MyConverter  # 註冊到converters


# 會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/center/<re(r"\d{5,10}"):uid>')  # 代表個人中心頁
def center(uid):  # 檢視函式

    return 'your uid %s' % uid  # 返回內容


# 會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/login/<re(r"1[3456789]\d{9}"):phone>')  # 代表登入頁
def login(phone):  # 檢視函式

    return 'your phone %s' % phone  # 返回內容


if __name__ == '__main__':
    # 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
    app.run(host='0.0.0.0', port=5000)  # 執行程式


複製程式碼

當我們請求的時候發現:

在這裡插入圖片描述
如果還繼續返回value呢?

   def to_python(self, value):
        return value  # 返回value
複製程式碼

在這裡插入圖片描述
看到這我們應該明白了,父類裡面預設返回的值就是正則匹配的值,如果重寫了,傳入進來的value還是正則匹配的值,但是return的值我們可以自己改變了。比如你傳的是13888888888,那我就返回13999999999在這才有轉換的體現。到底返回什麼樣的值,還是看具體場景。

  • 重寫to_url 不知道還記得我們的重定向嗎?我們可以通過重定向到任何檢視中。如果我們現在希望登入函式重定向到個人中心檢視怎麼辦?直接寫函式名字,好像不對了,因為現在路由需要一個UID引數。我們需要像下面這麼寫,並且我們在to_url方法呢隨便返回點內容:
from flask import Flask
from flask import abort, redirect, url_for
from werkzeug.routing import BaseConverter

app = Flask(__name__)


# 自定義轉換器
class MyConverter(BaseConverter):

    def __init__(self, map, re):
        super().__init__(map)  # 呼叫父類
        self.regex = re  # 轉換器的正則規則

    def to_python(self, value):
        return value  # 返回value

    def to_url(self, value):
        return '呵呵'  # 隨便返回點內容


app.url_map.converters['re'] = MyConverter  # 註冊到converters


# 會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/center/<re(r"\d{5,10}"):uid>')  # 代表個人中心頁
def center(uid):  # 檢視函式
    return 'your uid %s' % uid  # 返回內容


# 會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/login/<re(r"1[3456789]\d{9}"):phone>')  # 代表登入頁
def login(phone):  # 檢視函式
    return redirect(url_for('center', uid='11111'))  # 重定向到個人中心頁,uid是路由上的引數


if __name__ == '__main__':
    # 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
    app.run(host='0.0.0.0', port=5000)  # 執行程式

複製程式碼

我們在瀏覽器試一下:http://127.0.0.1:5000/login/13812345678

在這裡插入圖片描述
注意瀏覽器center後面的UID變成了呵呵兩個字。 如果還繼續返回value呢?

    def to_url(self, value):
        return value  # 返回value
複製程式碼

我們在瀏覽器試一下:http://127.0.0.1:5000/login/13812345678

在這裡插入圖片描述
如果我們我們這改下程式碼:

    def to_python(self, value):
        return '12312'  

    def to_url(self, value):
        return value  # 返回value
複製程式碼

在這裡插入圖片描述
寫到這,我們可以簡單總結一下這兩個函式什麼時候執行

  • to_python 只要使了轉換器,一直會被呼叫
  • to_url 只有在重定向了,並且路由上有引數的時候才會被呼叫

當我們重定向了,並傳遞引數的時候,引數會先到to_url,返回的值會去匹配路由上的正則。 如果匹配上了,就把匹配到引數傳到 to_python ,這個方法返回的值才會到檢視函式中。 如果匹配不上,就會報404錯誤。 流程如下:

在這裡插入圖片描述

歡迎關注我的公眾號:

Flask框架從入門到精通之轉換器(四)

相關文章