Flask實戰(zhàn)項目,相關筆記(一)

在使用Flask做項目的過程中,總結了一些知識點,因此寫了這份筆記,主要內(nèi)容有:

  1. 兼容帶 / 的URL
  2. 修改代碼后如何自動重啟
  3. 路由注冊
  4. 聊一聊if ... main的判斷
  5. 視圖函數(shù)的奧秘
  6. 配置文件的注意事項

兼容帶 / 的URL

我們訪問網(wǎng)頁的時候,比如我的簡書首頁,使用下面兩個URL都可以訪問到:

  1. http://www.lxweimin.com/u/8f1bb9388ce9
  2. http://www.lxweimin.com/u/8f1bb9388ce9/

區(qū)別在哪里呢,眼尖的你一定會發(fā)現(xiàn),區(qū)別在URL尾部是否有 / 。
那么如果我們用flask新建了一個項目,端口是8001,并且寫了這樣的視圖函數(shù)

@app.route('/hello')
def index():
    return 'Hello, my friend!'

那么使用http://127.0.0.1:8001/hello是可以訪問的:

hello1.png

但是使用http://127.0.0.1:8001/hello/是不行的:
hello2.png

那么我們?nèi)绾巫龅絻煞N寫法都可以訪問呢?
把上面代碼里的@app.route('/hello')改為@app.route('/hello/'),這樣就可以兼容 / 有、無的情形了:

下面我們再看為什么能夠兼容。把代碼修改成@app.route('/hello/')之后,確保flask服務已經(jīng)重啟,使用了最新代碼。然后打開瀏覽器的調(diào)試模式,看network這里,訪問http://127.0.0.1:8001/hello/ ,截圖如下:

image.png

你會發(fā)現(xiàn)是一下子就找到了這個路由,返回了200.

那么訪問http://127.0.0.1:8001/hello看看呢?

image.png

這里不一樣了,先訪問hello,返回一個status=301的重定向,然后再訪問到hello/,這時返回status=200,也展現(xiàn)出了正確的結果。
因此flask是采用了重定向的方式進行兼容,把不帶/的URL重定向到了帶/的URL上面。

那么為什么flask要這樣做?

因為flask遵循了唯一URL原理。所以要做一個這樣的重定向,保證唯一URL。
如果我們沒有用唯一的話,同一個視圖函數(shù)對應兩個不同的URL,就會被搜索引擎索引兩次。再往后深入,就會涉及到SEO,搜索引擎的優(yōu)化。這里我們就不繼續(xù)了。

修改代碼后如何自動重啟

實戰(zhàn)過程中,經(jīng)常需要修改代碼之后再重新啟動flask服務,手工的話比較麻煩,怎么辦呢?
flask內(nèi)置了自動重啟,只需要開啟調(diào)試模式即可。
app.run(debug=True)
啟動之后,提示:debugger is active!

注意,生產(chǎn)上不能用調(diào)試模式:

  1. 性能差、使用的是flask自帶的服務器。
  2. 不能把網(wǎng)站的詳細信息暴露給用戶

路由注冊

路由注冊有兩種寫法:

  1. 一種正如上面我們提到的@app.route('/hello')那樣,裝飾器或注解的方式(Python、C#、Java等語言支持),非常優(yōu)雅方便,缺點是不夠靈活
  2. app.add_url_rule('/hello', view_func=hello) 的注冊方式。

那么看看區(qū)別,裝飾器中沒有指定view_func,這是因為裝飾器打在了需要裝飾的函數(shù)上面,所以不需要指定view_func

建議:絕大多數(shù)情況下使用裝飾器(雖然裝飾器實際上也是調(diào)用app.add_url_rule實現(xiàn)的,不過這種裝飾器的封裝看起來更為優(yōu)雅)。

如果需要使用基于類的視圖(即插視圖),就必須需要使用app.add_url_rule來注冊。

聊一聊if ... main的判斷

我們經(jīng)常會用到這樣一句判斷if __name__ == '__main__':,大家應該也知道,如果這個文件是作為模塊被導入的,那么這一行下面的代碼不會被執(zhí)行。

具體到flask項目文件里面,我們會在app.run的相關代碼之前,寫上這樣一行判斷,那么為什么要增加這一行判斷,之后再啟動服務器?
在開發(fā)環(huán)境,啟動的web服務器是flask自帶的非常簡單的服務器,但是部署到生產(chǎn)環(huán)境一般不用,會用nginx(前置服務器,接受瀏覽器發(fā)來的請求,然后轉發(fā)成uwsgi)+uwsgi。
uwsgi加載模塊,啟動相關代碼,此時這個文件就不再是入口文件,而是被加載的入口文件,app.run就不會執(zhí)行。
如果缺少這個if判斷,生產(chǎn)環(huán)境加載了這個文件之后,app.run就會執(zhí)行——啟動兩個服務器是不可以的。
因此先加上這個if判斷,保證生產(chǎn)環(huán)境不會啟動flask自帶的服務器。

視圖函數(shù)的奧秘

和普通函數(shù)不一樣,它除了返回主要的內(nèi)容之外,還會返回一系列附加信息:
例如,status狀態(tài)碼,content-type http header
告訴接收方如何解析返回的主體內(nèi)容。視圖函數(shù)如果返回的是一串文本,如何解析這串文本,默認情況下(不指定content-type),默認值content-type = text/html。
flask返回的還有一些其他的內(nèi)容,但是主要關注這三個內(nèi)容:status, content-type, 返回的那個字符串.

flask會把所有返回的內(nèi)容,封裝成Response對象。

如何創(chuàng)建Response對象?make_response()

headers = {
    'content-type':'text/plain'
}
response = make_response('<html></html>', 404)
response.headers = headers
returen response

狀態(tài)碼并不會對內(nèi)容產(chǎn)生影響,狀態(tài)碼只是一個標識而已。

比如 301

headers = {
    'content-type':'text/plain'
    'location':'www.bing.com'
}
response = make_response('<html></html>', 301)

就會重定向到bing這個網(wǎng)站。

如果返回json格式怎么辦?content-type改成json,返回的內(nèi)容寫成一個json字符串。

web返回的內(nèi)容,本質(zhì)上都是一個字符串,控制的因素在content-type,指定了要如何解釋我們的返回。

return '<html></html>', 301, headers # 這樣返回元組也可以,flask會把元組轉換成Response對象再返回回去。

配置文件的注意事項

我們一般會想到新建一個config.py,并寫入自己的配置:

config.py
DEBUG= True

使用app.config.from_object('config')可以導入一個配置文件
入?yún)⑹且粋€模塊的路徑,比如config和本文件在一個目錄下,就可以這樣寫
debug=app.config['DEBUG']

但是有一個問題,如果:

config.py
Debug = True

打印app.config['DEBUG'],則是False
打印app.config['Debug'],則是報錯,為何?!

解答:

  1. DEBUG在flask里面是一個默認參數(shù),默認值是False
  2. 若以from_object的形式載入?yún)?shù),flask要求,配置參數(shù)名必須都是大寫,小寫的讀取不到。

因此,上面app.config['Debug']的情況下,其實是找不到配置參數(shù)的;而
app.config['DEBUG']則是讀取了flask的默認參數(shù)呢!

所以自己使用的時候,要記住這點,就不會在報錯的時候感到奇怪。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容