Flask學(xué)習(xí)之旅 --- 初級(jí)篇

1. Flask簡(jiǎn)介:

flask是一款非常流行的Python Web框架,出生于2010年,作者是Armin Ronacher,本來這個(gè)項(xiàng)目只是作者在愚人節(jié)的一個(gè)玩笑,后來由于非常受歡迎,進(jìn)而成為一個(gè)正式的項(xiàng)目。目前為止最新的版本是0.12.2。

flask自2010年發(fā)布第一個(gè)版本以來,大受歡迎,深得開發(fā)者的喜愛,并且在多個(gè)公司已經(jīng)得到了應(yīng)用,flask能如此流行的原因,可以分為以下幾點(diǎn):

  • 微框架、簡(jiǎn)潔、只做他需要做的,給開發(fā)者提供了很大的擴(kuò)展性。
  • Flask和相關(guān)的依賴(Jinja2、Werkzeug)設(shè)計(jì)得非常優(yōu)秀,用起來很爽。
  • 開發(fā)效率非常高,比如使用SQLAlchemyORM操作數(shù)據(jù)庫可以節(jié)省開發(fā)者大量書寫sql的時(shí)間。
  • 社會(huì)活躍度非常高。

Flask的靈活度非常之高,他不會(huì)幫你做太多的決策,即使做已經(jīng)幫你做出選擇,你也能非常容易的更換成你需要的,比如:

  • 使用Flask開發(fā)數(shù)據(jù)庫的時(shí)候,具體是使用SQLAlchemy還是MongoEngine或者是不用ORM而直接基于MySQL-Python這樣的底層驅(qū)動(dòng)進(jìn)行開發(fā)都是可以的,選擇權(quán)完全掌握在你自己的手中。區(qū)別于Django,Django內(nèi)置了非常完善和豐富的功能,并且如果你想替換成你自己想要的,要么不支持,要么非常麻煩。
  • 把默認(rèn)的Jinija2模板引擎替換成Mako引擎或者是其他模板引擎都是非常容易的。

flask文檔

中文文檔: http://docs.jinkan.org/docs/flask/

英文文檔: http://flask.pocoo.org/docs/0.12/

2. 第一個(gè)flask程序:

pycharm新建一個(gè)flask項(xiàng)目,新建項(xiàng)目的截圖如下:


點(diǎn)擊create后創(chuàng)建一個(gè)新項(xiàng)目,然后在helloworld.py文件中書寫代碼:

    #coding: utf8    

    # 從flask框架中導(dǎo)入Flask類
    from flask import Flask

    # 傳入__name__初始化一個(gè)Flask實(shí)例
    app = Flask(__name__)

    # app.route裝飾器映射URL和執(zhí)行的函數(shù)。這個(gè)設(shè)置將根URL映射到了hello_world函數(shù)上
    @app.route('/')
    def hello_world():
        return 'Hello World!'

    if __name__ == '__main__':
        # 運(yùn)行本項(xiàng)目,host=0.0.0.0可以讓其他電腦也能訪問到該網(wǎng)站,port指定訪問的端口。默認(rèn)的host是127.0.0.1,port為5000
        app.run(host='0.0.0.0',port=9000)

然后點(diǎn)擊運(yùn)行,在瀏覽器中輸入http://127.0.0.1:9000就能看到hello world了。需要說明一點(diǎn)的是,app.run這種方式只適合于開發(fā),如果在生產(chǎn)環(huán)境中,應(yīng)該使用Gunicorn或者uWSGI來啟動(dòng)。如果是在終端運(yùn)行的,可以按ctrl+c來讓服務(wù)停止。

3. Flask創(chuàng)建app對(duì)象

3.1初始化參數(shù)

app = Flask()的可選參數(shù):
import_name: 導(dǎo)入路徑(尋找靜態(tài)目錄與模板目錄位置的參數(shù)),一般寫__name__。
static_url_path:訪問靜態(tài)資源的前綴,默認(rèn)static,這個(gè)前綴目錄下都是靜態(tài)資源。
static_folder: 靜態(tài)目錄的名字,默認(rèn)static,其實(shí)就是項(xiàng)目中項(xiàng)目目錄存放靜態(tài)資源文件夾的名字。
template_folder: 模板目錄的名字,默認(rèn)templates, 其實(shí)就是項(xiàng)目中項(xiàng)目目錄存放模板文件文件夾的名字。

3.2 配置參數(shù)

有4種,一般使用app.config.from_pyfileapp.config.from_objectapp.config[key]=value,app.config.from_envvar是從虛擬環(huán)境中讀取配置參數(shù)(一般不用):

  1. 使用配置文件,項(xiàng)目里新建一個(gè)文件,把相關(guān)的配置寫到該文件中然后通過app對(duì)象的config屬性的from_pyfile 方式來導(dǎo)入配置文件。如在項(xiàng)目目錄中定義配置文件為“config.cfg”,在程序中引入配置文件方式:app.config.from_pyfile(“config.cfg”),路徑可以是相對(duì)路徑或者絕對(duì)路徑,這種方式,可以傳遞silent=True,那么這個(gè)靜態(tài)文件沒有找到的時(shí)候,不會(huì)拋出異常。
app.config.from_pyfile('config.cfg',silent=True)
# silent=True表示如果配置文件不存在的時(shí)候不拋出異常,默認(rèn)是為False,會(huì)拋出異常。
  1. 從對(duì)象中導(dǎo)入,一般是定義一個(gè)配置參數(shù)的類(類名可以自定義,一般類名是Config),再把相關(guān)的參數(shù)配置以類屬性的方式定義,然后通過app對(duì)象的config屬性的from_ object方式來導(dǎo)入。如定義一個(gè)Config類:
class Config(object):  
        DEBUG = True

導(dǎo)入方式:app.config.from_object(Config),可以不用實(shí)例化一個(gè)Config對(duì)象,因?yàn)轭愐彩菍?duì)象,flask會(huì)自動(dòng)從Config類中讀取參數(shù)

  1. 可以通過app.config[key]=value,類似于字典的方式直接把相關(guān)的配置參數(shù)加上。如:
app = Flask(__name__)
app.config['DEBUG'] = True

3.3 在視圖讀取配置參數(shù)

app.config.get()按照字典取值的方法獲取配置參數(shù)的值或者是先導(dǎo)入current_app再用current_app.config.get()按照字典取值的方法獲取配置參數(shù)的值

3.4 app.run的參數(shù)

啟動(dòng)app可以傳參數(shù),比如host、port,debug,如果是配置參數(shù),配置參數(shù)只能傳debug

app.run(host="0.0.0.0", port=5000,debug=True)

4. debug模式

4.1 為什么需要開啟DEBUG模式

  1. 如果開啟了DEBUG模式,那么在代碼中如果拋出了異常,在瀏覽器的頁面中可以看到具體的錯(cuò)誤信息,以及具體的錯(cuò)誤代碼位置。方便開發(fā)者調(diào)試。
  2. 如果開啟了DEBUG模式,那么以后在Python代碼中修改了任何代碼,只要按ctrl+s,flask就會(huì)自動(dòng)的重新記載整個(gè)網(wǎng)站。不需要手動(dòng)點(diǎn)擊重新運(yùn)行。

4.2 debug配置的5種方式

  1. 使用配置文件,項(xiàng)目里新建一個(gè)文件,把相關(guān)的配置寫到該文件中然后通過app對(duì)象的config屬性的from_pyfile方式來導(dǎo)入配置文件。如在項(xiàng)目目錄中定義配置文件為“config.cfg”,在程序中引入配置文件方式:app.config.from_pyfile(“config.cfg”),路徑可以是相對(duì)路徑或者絕對(duì)路徑,這種方式,可以傳遞silent=True,那么這個(gè)靜態(tài)文件沒有找到的時(shí)候,不會(huì)拋出異常。

  2. 從對(duì)象中導(dǎo)入,一般是定義一個(gè)配置參數(shù)的類(類名可以自定義,一般類名是Config),再把相關(guān)的參數(shù)配置以類屬性的方式定義,然后通過app對(duì)象的config屬性的from_ object 方式來導(dǎo)入。如定義一個(gè)Config類:

class Config(object):  
        DEBUG = True 

導(dǎo)入方式:app.config.from_object(Config),可以不用實(shí)例化一個(gè)Config對(duì)象,因?yàn)轭愐彩菍?duì)象,flask會(huì)自動(dòng)從Config類中讀取參數(shù)。

  1. 可以通過app.config[key]=value,類似于字典的方式直接把相關(guān)的配置參數(shù)加上。如app.config["DEBUG"]=True

  2. 直接通過app.debug = True的方式

  3. 通過給app.config添加參數(shù)的方式(類似于添加字典),app.config.update(DEBUG = True)

4.3 PIN碼

開啟了debug模式后,flask會(huì)自動(dòng)生成一個(gè)PIN碼,PIN碼用于頁面調(diào)試如果想要在網(wǎng)頁上調(diào)試代碼,那么應(yīng)該輸入PIN碼。

5. url詳解

5.1 在局域網(wǎng)中讓其他電腦訪問我的網(wǎng)站

如果想在同一個(gè)局域網(wǎng)下的其他電腦訪問自己電腦上的Flask網(wǎng)站,那么可以在app.run()中設(shè)置host='0.0.0.0'才能訪問得到。

5.2 指定端口號(hào)

Flask項(xiàng)目,默認(rèn)使用5000端口。如果想更換端口,那么可以在app.run()中設(shè)置port=9000

5.3 url唯一

在定義url的時(shí)候,一定要記得在最后加一個(gè)斜杠。

  1. 如果不加斜杠,那么在瀏覽器中訪問這個(gè)url的時(shí)候,如果最后加了斜杠,那么就訪問不到。這樣用戶體驗(yàn)不太好。
  2. 搜索引擎會(huì)將不加斜杠的和加斜杠的視為兩個(gè)不同的url。而其實(shí)加和不加斜杠的都是同一個(gè)url,那么就會(huì)給搜索引擎造成一個(gè)誤解。加了斜杠,就不會(huì)出現(xiàn)沒有斜杠的情況。

5.4 GET請(qǐng)求和POST請(qǐng)求

在網(wǎng)絡(luò)請(qǐng)求中有許多請(qǐng)求方式,比如:GET、POST、DELETE、PUT請(qǐng)求等。那么最常用的就是GETPOST請(qǐng)求了。

  1. GET請(qǐng)求:只會(huì)在服務(wù)器上獲取資源,不會(huì)更改服務(wù)器的狀態(tài)。這種請(qǐng)求方式推薦使用GET請(qǐng)求。

  2. POST請(qǐng)求:會(huì)給服務(wù)器提交一些數(shù)據(jù)或者文件。一般POST請(qǐng)求是會(huì)對(duì)服務(wù)器的狀態(tài)產(chǎn)生影響,那么這種請(qǐng)求推薦使用POST請(qǐng)求。

  3. 關(guān)于參數(shù)傳遞:

    • GET請(qǐng)求:把參數(shù)放到url中,通過?xx=xxx的形式傳遞的。因?yàn)闀?huì)把參數(shù)放到url中,所以如果視力好,一眼就能看到你傳遞給服務(wù)器的參數(shù)。這樣不太安全。
    • POST請(qǐng)求:把參數(shù)放到Form Data中。會(huì)把參數(shù)放到Form Data中,避免了被偷瞄的風(fēng)險(xiǎn),但是如果別人想要偷看你的密碼,那么其實(shí)可以通過抓包的形式。因?yàn)?code>POST請(qǐng)求可以提交一些數(shù)據(jù)給服務(wù)器,比如可以發(fā)送文件,那么這就增加了很大的風(fēng)險(xiǎn)。所以POST請(qǐng)求,對(duì)于那些有經(jīng)驗(yàn)的黑客來講,其實(shí)是更不安全的。
  4. Flask中,route方法,默認(rèn)將只能使用GET的方式請(qǐng)求這個(gè)url,如果想要設(shè)置自己的請(qǐng)求方式,那么應(yīng)該傳遞一個(gè)methods參數(shù)來限制訪問方式。

@app.route('/sample', methods=['GET', 'POST'])
def my_list(page):
    return 'my list'

5.5 url與函數(shù)的映射

從之前的helloworld.py文件中,我們已經(jīng)看到,一個(gè)URL要與執(zhí)行函數(shù)進(jìn)行映射,使用的是@app.route裝飾器。@app.route裝飾器中,可以指定URL的規(guī)則來進(jìn)行更加詳細(xì)的映射,比如現(xiàn)在要映射一個(gè)文章詳情的URL,文章詳情的URL是/article/id/,id有可能為1、2、3...,那么可以通過以下方式:

   @app.route('/article/<id>/')
   def article(id):
       return '%s article detail' % id

其中<id>,尖括號(hào)是固定寫法,語法為<variable_name>,variable_name默認(rèn)的數(shù)據(jù)類型是字符串。如果需要指定類型,則要寫成<converter:variable_name>,其中converter就是類型名稱,可以有以下幾種:
string: 默認(rèn)的數(shù)據(jù)類型,接受沒有任何斜杠“/”的文本。
int: 接受整形。
float: 接受浮點(diǎn)類型。
path: 和string的類似,但是接受斜杠。
uuid: 只接受uuid字符串。
any:可以指定多種路徑,這個(gè)通過一個(gè)例子來進(jìn)行說明:

  @app.route('/<any(article,blog):url_path>/')
  def item(url_path):
      return url_path

以上例子中,item這個(gè)函數(shù)可以接受兩個(gè)URL,一個(gè)是/article/,另一個(gè)是/blog/。并且,一定要傳url_path參數(shù),當(dāng)然這個(gè)url_path的名稱可以隨便。

如果不想定制子路徑來傳遞參數(shù),也可以通過傳統(tǒng)的?=的形式來傳遞參數(shù),例如:/article?id=xxx,這種情況下,可以通過request.args.get('id')來獲取id的值。如果是post方法,則可以通過request.form.get('id')來進(jìn)行獲取。

6. url_for詳解

6.1 url_for的基本使用

url_for第一個(gè)參數(shù),應(yīng)該是視圖函數(shù)的名字的字符串。后面的參數(shù)就是傳遞給url。如果傳遞的參數(shù)之前在url中已經(jīng)定義了,那么這個(gè)參數(shù)就會(huì)被當(dāng)成path的形式給url。如果這個(gè)參數(shù)之前沒有在url中定義,那么將變成查詢字符串的形式放到url中。

@app.route('/post/list/<page>/')
def my_list(page):
    return 'my list'

print(url_for('my_list',page=1,count=2))
# 構(gòu)建出來的url:/my_list/1/?count=2

6.2 為什么需要url_for

  1. 將來如果修改了URL,但沒有修改該URL對(duì)應(yīng)的函數(shù)名,就不用到處去替換URL了。
  2. url_for會(huì)自動(dòng)的處理那些特殊的字符,不需要手動(dòng)去處理。
  3. 強(qiáng)烈建議以后在使用url的時(shí)候,使用url_for來反轉(zhuǎn)url。
 url = url_for('login',next='/')
    # 會(huì)自動(dòng)的將/編碼,不需要手動(dòng)去處理。
    # url=/login/?next=%2F

7. 動(dòng)態(tài)路由

7.1 傳遞參數(shù)

傳遞參數(shù)的語法是:/<參數(shù)名>/。然后在視圖函數(shù)中,也要定義同名的參數(shù)。

7.2 參數(shù)的數(shù)據(jù)類型

  1. 如果沒有指定具體的數(shù)據(jù)類型,那么默認(rèn)就是使用string數(shù)據(jù)類型。
  2. int數(shù)據(jù)類型只能傳遞int類型。
  3. float數(shù)據(jù)類型只能傳遞float類型。
  4. path數(shù)據(jù)類型和string有點(diǎn)類似,都是可以接收任意的字符串,但是path可以接收路徑,也就是說可以包含斜杠。
  5. uuid數(shù)據(jù)類型只能接收符合uuid的字符串。uuid是一個(gè)全宇宙都唯一的字符串,一般可以用來作為表的主鍵。
  6. any數(shù)據(jù)類型可以在一個(gè)url中指定多個(gè)路徑。例如:
    @app.route('/<any(blog,article):url_path>/<id>/')
    def detail(url_path,id):
        if url_path == 'blog':
            return '博客詳情:%s' % id
        else:
            return '博客詳情:%s' % id
    
    # 路由傳遞的參數(shù)默認(rèn)當(dāng)做string處理,這里指定int,尖括號(hào)中冒號(hào)后面的內(nèi)容是動(dòng)態(tài)的
    @app.route('/user/<int:id>')
    def hello_itcast(id):
        return 'hello word %d' %id
    

7.3 接收用戶傳遞的參數(shù)

  1. 第一種:使用path的形式(將參數(shù)嵌入到路徑中),就是上面講的。
  2. 第二種:使用查詢字符串的方式,就是通過?key=value的形式傳遞的。
    @app.route('/d/')
    def d():
        wd = request.args.get('wd')
        return '您通過查詢字符串的方式傳遞的參數(shù)是:%s' % wd
    
  3. 如果你的這個(gè)頁面的想要做SEO優(yōu)化,就是被搜索引擎搜索到,那么推薦使用第一種形式(path的形式)。如果不在乎搜索引擎優(yōu)化,那么就可以使用第二種(查詢字符串的形式)。

7.4 app.url_map`查看所有路由

通過app.url_map可以查看整個(gè)flask中的路由信息

7.5 同一路由裝飾多個(gè)視圖函數(shù)

如果兩個(gè)路由的請(qǐng)求方式相同,那么先定義的視圖函數(shù)將會(huì)覆后定義的視圖函數(shù),如果不同則根據(jù)請(qǐng)求方式來調(diào)用視圖

@app.route('/index')
def index():
    return "hello"
@app.route('/index')
def index1():
    return "hello1"

上面這種情況,在瀏覽器訪問index,只會(huì)執(zhí)行第一個(gè)視圖函數(shù),第二個(gè)視圖函數(shù)將會(huì)被覆蓋

@app.route('/index', methods=['POST'])
def index():
    return "hello"
@app.route('/index', methods=['GET'])
def index1():
    return "hello1"

上面這種方式,會(huì)根據(jù)請(qǐng)求方式來決定執(zhí)行那個(gè)視圖

7.6 同一視圖多個(gè)路由裝飾器

裝飾器層疊就可以

@app.route('/index')
@app.route('/index1')
def index():
    return "hello"

8. 自定義URL轉(zhuǎn)換器

8.1 自定義URL轉(zhuǎn)換器的方式

  1. 轉(zhuǎn)換器是一個(gè)類,且必須繼承自werkzeug.routing.BaseConverter。
  2. 在轉(zhuǎn)換器類中,實(shí)現(xiàn)to_python(self,value)方法,這個(gè)方法的返回值,將會(huì)傳遞到view函數(shù)中作為參數(shù)。
  3. 在轉(zhuǎn)換器類中,實(shí)現(xiàn)to_url(self,values)方法,這個(gè)方法的返回值,將會(huì)在調(diào)用url_for函數(shù)的時(shí)候生成符合要求的URL形式。
  4. 在自定義的類中,重寫regex,也就是這個(gè)變量的正則表達(dá)式。
  5. 將自定義的類,映射到app.url_map.converters上。比如:
    app.url_map.converters['tel'] = TelephoneConverter
    

8.2 to_python的作用

這個(gè)方法的返回值,將會(huì)傳遞到view函數(shù)中作為參數(shù)。

8.3 to_url的作用

這個(gè)方法的返回值,將會(huì)在調(diào)用url_for函數(shù)的時(shí)候生成符合要求的url形式。

8.4 萬能轉(zhuǎn)換器

可以定義一個(gè)正則的萬能表達(dá)式,可以根據(jù)傳入的正則表達(dá)式提取相關(guān)參數(shù):

from flask import Flask
from werkzeug.routing import BaseConverter

class Regex_url(BaseConverter):
    def __init__(self,url_map,*args):
        super(Regex_url,self).__init__(url_map)
        self.regex = args[0]

app = Flask(__name__)
app.url_map.converters['re'] = Regex_url

@app.route('/user/<re("[a-z]{3}"):id>')
def hello_itcast(id):
    return 'hello %s' %id

9. redirect重定向

9.1 重定向分類

重定向分為永久性重定向和暫時(shí)性重定向,在頁面上體現(xiàn)的操作就是瀏覽器會(huì)從一個(gè)頁面自動(dòng)跳轉(zhuǎn)到另外一個(gè)頁面。比如用戶訪問了一個(gè)需要權(quán)限的頁面,但是該用戶當(dāng)前并沒有登錄,因此我們應(yīng)該給他重定向到登錄頁面。

  • 永久性重定向:http的狀態(tài)碼是301,多用于舊網(wǎng)址被廢棄了要轉(zhuǎn)到一個(gè)新的網(wǎng)址確保用戶的訪問,最經(jīng)典的就是京東網(wǎng)站,你輸入www.jingdong.com的時(shí)候,會(huì)被重定向到www.jd.com,因?yàn)?code>jingdong.com這個(gè)網(wǎng)址已經(jīng)被廢棄了,被改成jd.com,所以這種情況下應(yīng)該用永久重定向。

  • 暫時(shí)性重定向:http的狀態(tài)碼是302,表示頁面的暫時(shí)性跳轉(zhuǎn)。比如訪問一個(gè)需要權(quán)限的網(wǎng)址,如果當(dāng)前用戶沒有登錄,應(yīng)該重定向到登錄頁面,這種情況下,應(yīng)該用暫時(shí)性重定向。

9.2 flask中重定向

flask中有一個(gè)函數(shù)叫做redirect,可以重定向到指定的頁面。示例代碼如下:

# 先導(dǎo)入redirect
from flask import Flask,request,redirect,url_for

app = Flask(__name__)

@app.route('/login/')
def login():
    return '這是登錄頁面'

@app.route('/profile/')
def profile():
    if request.args.get('name'):
        return '個(gè)人中心頁面'
    else:
        # redirect 重定向
        return redirect(url_for('login'))

10. response詳解

10.1 視圖函數(shù)中可以返回哪些值

  1. 可以返回字符串:返回的字符串其實(shí)底層將這個(gè)字符串包裝成了一個(gè)Response對(duì)象。
  2. 可以返回元組:這樣的元組必須是 (response, status, headers)的形式,且至少包含一個(gè)元素。 status值會(huì)覆蓋狀態(tài)代碼,headers可以是一個(gè)列表或字典,作為額外的消息標(biāo)頭值。元組的形式是(響應(yīng)體,狀態(tài)碼,頭部信息),也不一定三個(gè)都要寫,寫兩個(gè)也是可以的。返回的元組,其實(shí)在底層也是包裝成了一個(gè)Response對(duì)象。
  3. 可以返回Response及其子類。

10.2 實(shí)現(xiàn)一個(gè)自定義的Response對(duì)象

  1. 繼承自Response類。
  2. 實(shí)現(xiàn)方法force_type(cls,rv,environ=None)。
  3. 指定app.response_class為你自定義的Response對(duì)象。
  4. 如果視圖函數(shù)返回的數(shù)據(jù),不是字符串,也不是元組,也不是Response對(duì)象,那么就會(huì)將返回值傳給force_type,然后再將force_type的返回值返回給前端。
from flask import Flask,Response,jsonify,render_template
# flask = werkzeug+sqlalchemy+jinja2
import json

app = Flask(__name__)

# 將視圖函數(shù)中返回的字典,轉(zhuǎn)換成json對(duì)象,然后返回
# restful-api
class JSONResponse(Response):

    @classmethod
    def force_type(cls, response, environ=None):
        """
        這個(gè)方法只有視圖函數(shù)返回非字符、非元組、非Response對(duì)象
        才會(huì)調(diào)用
        response:視圖函數(shù)的返回值
        """
        if isinstance(response,dict):
            # jsonify除了將字典轉(zhuǎn)換成json對(duì)象,還將改對(duì)象包裝成了一個(gè)Response對(duì)象
            response = jsonify(response)
        return super(JSONResponse, cls).force_type(response,environ)

app.response_class = JSONResponse


@app.route('/')
def hello_world():
    # Response('Hello World!',status=200,mimetype='text/html')
    return 'Hello World!'

@app.route('/list1/')
def list1():
    resp = Response('list1')
    resp.set_cookie('country','china')
    return resp

@app.route('/list2/')
def list2():
    return 'list2',200,{'X-NAME':'zhiliao'}

@app.route('/list3/')
def list3():
    return {'username':'zhiliao','age':18}

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

10.3 abort函數(shù)

  1. abort() : 立即停止視圖函數(shù)的執(zhí)行,并且把相對(duì)應(yīng)的信息返回到前端中使用abort函數(shù)可以立即終止視圖函數(shù)的執(zhí)行 并可以返回給前端特定的信息abort()函數(shù)可以傳遞兩種方式的信息,

    (1) ①:一種是傳遞狀態(tài)碼信息,例如:abort(404),前端就會(huì)報(bào)出已經(jīng)默認(rèn)好的404錯(cuò)誤信息
    ②:自定義錯(cuò)誤信息,(用裝飾器)定義一個(gè)視圖函數(shù)這個(gè)函數(shù)的返回值會(huì)是前端所看到的最終的結(jié)果,這個(gè)視圖函數(shù)的裝飾器來定義錯(cuò)誤的類型

    @app.errorhandler(404)   # 定義404的錯(cuò)誤類型
    

    自定義的錯(cuò)誤類型,要和abort()里面定義的錯(cuò)誤類型一致

    (2) 另外一種方式是傳遞響應(yīng)體的信息,abort(Response("內(nèi)容")),Response() ,里面的信息會(huì)在前端上面顯示出來

    代碼:404錯(cuò)誤...加上自定義的錯(cuò)誤信息如果使用傳遞響應(yīng)體信息的話就會(huì)只有響應(yīng)體信息的錯(cuò)誤異常

from flask import Flask, request, abort,Response

app = Flask(__name__)


@app.route("/login", methods=["GET"])
def login():
    name = ""
    pwd = ""
    if name != "zhangsan" or pwd != "admin":
        """
            使用abort函數(shù)可以立即終止視圖函數(shù)的執(zhí)行
            并可以返回給前端特定的信息
            1. 傳遞狀態(tài)碼信息,必須是標(biāo)準(zhǔn)的http狀態(tài)碼
            可以接受狀態(tài)碼信息,返回給前端已經(jīng)默認(rèn)好的信息
        """
        abort(404)
        """
            2. 傳遞響應(yīng)體的信息, Response()里面的內(nèi)容會(huì)在前端上顯示出來
            resp = Response("login failed")
            abort(resp)
        """
    return "login success"


"""自定義異常處理"""
@app.errorhandler(404)
def handle_404_error(error):  # 接受一個(gè)錯(cuò)誤信息
    """自定義的處理404錯(cuò)誤方法"""
    '''這個(gè)函數(shù)的返回值會(huì)是前端所看到的最終的結(jié)果'''
    return "出現(xiàn)了404錯(cuò)誤,錯(cuò)誤信息:%s"%error


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

10.4 自定義異常處理

自定義錯(cuò)誤信息,(用裝飾器)定義一個(gè)視圖函數(shù)這個(gè)函數(shù)的返回值會(huì)是前端所看到的最終的結(jié)果,這個(gè)視圖函數(shù)的裝飾器來定義錯(cuò)誤的類型

@app.errorhandler(404)
def error(e):
    return '您請(qǐng)求的頁面不存在了,請(qǐng)確認(rèn)后再次訪問!%s'%e

10.5 make_response()詳解

make_response(),相當(dāng)于DJango中的HttpResponse。
1.返回內(nèi)容

from flask import make_response

@blue.route('/makeresponse/')
def make_response_function():
    response = make_response('<h2>羞羞噠</h2>')
    return response, 404

2.返回頁面

from flask import make_response

@blue.route('/makeresponse/')
def make_response_function():
    temp = render_template('hello.html')
    response = make_response(temp)
    return response
  • 注意:make_response 想要返回頁面,不能直接寫做:make_response('hello.html'),必須用render_template('hello.html')形式。

3.返回狀態(tài)碼

  • 方式一:在make_response()中傳入狀態(tài)碼
from flask import make_response

@blue.route('/makeresponse/')
def make_response_function():
    temp = render_template('hello.html')
    response = make_response(temp, 200)
    return response
  • 方式二:直接return狀態(tài)碼
from flask import make_response

@blue.route('/makeresponse/')
def make_response_function():
    temp = render_template('hello.html')
    response = make_response(temp)
    return response, 200

11. 獲取請(qǐng)求參數(shù)

11.1 request詳解

獲取請(qǐng)求參數(shù)時(shí)首先要導(dǎo)入request模塊

from flask import request

就是 Flask 中表示當(dāng)前請(qǐng)求的request對(duì)象,request對(duì)象中保存了一次HTTP請(qǐng)求的一切信息。

11.2 request的常用屬性

  1. methods
    默認(rèn)的請(qǐng)求方式只有GET,其他請(qǐng)求都需要通過參數(shù)methods進(jìn)行指定。
methods=['GET', 'POST']
  1. args:獲取GET請(qǐng)求參數(shù)
    flask中,要獲取get請(qǐng)求的參數(shù),不是通過request.GET.get(),而是通過request.args.get()獲取。
request.agrs.get('參數(shù)名')
  1. form:獲取POST請(qǐng)求參數(shù)
    flask中,要獲取get請(qǐng)求的參數(shù),不是通過request.POST.get(),而是通過request.form.get()獲取。
request.form.get('參數(shù)名')

11.3 上傳文件

已上傳的文件存儲(chǔ)在內(nèi)存或是文件系統(tǒng)中一個(gè)臨時(shí)的位置。你可以通過請(qǐng)求對(duì)象的files屬性訪問它們。每個(gè)上傳的文件都會(huì)存儲(chǔ)在這個(gè)字典里。它表現(xiàn)近乎為一個(gè)標(biāo)準(zhǔn)的 Python file對(duì)象,但它還有一個(gè) save()方法,這個(gè)方法允許你把文件保存到服務(wù)器的文件系統(tǒng)上。這里是一個(gè)用它保存文件的例子:

from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
    ...

如果你想知道上傳前文件在客戶端的文件名是什么,你可以訪問filename屬性。但請(qǐng)記住, 永遠(yuǎn)不要信任這個(gè)值,這個(gè)值是可以偽造的。如果你要把文件按客戶端提供的文件名存儲(chǔ)在服務(wù)器上,那么請(qǐng)把它傳遞給Werkzeug提供的secure_filename()函數(shù):

from flask import request
from werkzeug import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/' + secure_filename(f.filename))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容