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ā)效率非常高,比如使用
SQLAlchemy的ORM操作數(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_pyfile和app.config.from_object,app.config[key]=value,app.config.from_envvar是從虛擬環(huán)境中讀取配置參數(shù)(一般不用):
- 使用配置文件,項(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ì)拋出異常。
- 從對(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ù)
- 可以通過
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模式
- 如果開啟了
DEBUG模式,那么在代碼中如果拋出了異常,在瀏覽器的頁面中可以看到具體的錯(cuò)誤信息,以及具體的錯(cuò)誤代碼位置。方便開發(fā)者調(diào)試。 - 如果開啟了
DEBUG模式,那么以后在Python代碼中修改了任何代碼,只要按ctrl+s,flask就會(huì)自動(dòng)的重新記載整個(gè)網(wǎng)站。不需要手動(dòng)點(diǎn)擊重新運(yùn)行。
4.2 debug配置的5種方式
使用配置文件,項(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ì)拋出異常。從對(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ù)。
可以通過
app.config[key]=value,類似于字典的方式直接把相關(guān)的配置參數(shù)加上。如app.config["DEBUG"]=True直接通過
app.debug = True的方式通過給
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è)斜杠。
- 如果不加斜杠,那么在瀏覽器中訪問這個(gè)url的時(shí)候,如果最后加了斜杠,那么就訪問不到。這樣用戶體驗(yàn)不太好。
- 搜索引擎會(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)求等。那么最常用的就是GET和POST請(qǐng)求了。
GET請(qǐng)求:只會(huì)在服務(wù)器上獲取資源,不會(huì)更改服務(wù)器的狀態(tài)。這種請(qǐng)求方式推薦使用GET請(qǐng)求。POST請(qǐng)求:會(huì)給服務(wù)器提交一些數(shù)據(jù)或者文件。一般POST請(qǐng)求是會(huì)對(duì)服務(wù)器的狀態(tài)產(chǎn)生影響,那么這種請(qǐng)求推薦使用POST請(qǐng)求。-
關(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í)是更不安全的。
-
在
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
- 將來如果修改了
URL,但沒有修改該URL對(duì)應(yīng)的函數(shù)名,就不用到處去替換URL了。 -
url_for會(huì)自動(dòng)的處理那些特殊的字符,不需要手動(dòng)去處理。 - 強(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ù)類型
- 如果沒有指定具體的數(shù)據(jù)類型,那么默認(rèn)就是使用
string數(shù)據(jù)類型。 -
int數(shù)據(jù)類型只能傳遞int類型。 -
float數(shù)據(jù)類型只能傳遞float類型。 -
path數(shù)據(jù)類型和string有點(diǎn)類似,都是可以接收任意的字符串,但是path可以接收路徑,也就是說可以包含斜杠。 -
uuid數(shù)據(jù)類型只能接收符合uuid的字符串。uuid是一個(gè)全宇宙都唯一的字符串,一般可以用來作為表的主鍵。 -
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ù)
- 第一種:使用path的形式(將參數(shù)嵌入到路徑中),就是上面講的。
- 第二種:使用查詢字符串的方式,就是通過
?key=value的形式傳遞的。@app.route('/d/') def d(): wd = request.args.get('wd') return '您通過查詢字符串的方式傳遞的參數(shù)是:%s' % wd - 如果你的這個(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)換器的方式
- 轉(zhuǎn)換器是一個(gè)類,且必須繼承自
werkzeug.routing.BaseConverter。 - 在轉(zhuǎn)換器類中,實(shí)現(xiàn)
to_python(self,value)方法,這個(gè)方法的返回值,將會(huì)傳遞到view函數(shù)中作為參數(shù)。 - 在轉(zhuǎn)換器類中,實(shí)現(xiàn)
to_url(self,values)方法,這個(gè)方法的返回值,將會(huì)在調(diào)用url_for函數(shù)的時(shí)候生成符合要求的URL形式。 - 在自定義的類中,重寫
regex,也就是這個(gè)變量的正則表達(dá)式。 - 將自定義的類,映射到
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ù)中可以返回哪些值
- 可以返回字符串:返回的字符串其實(shí)底層將這個(gè)字符串包裝成了一個(gè)
Response對(duì)象。 - 可以返回元組:這樣的元組必須是
(response, status, headers)的形式,且至少包含一個(gè)元素。status值會(huì)覆蓋狀態(tài)代碼,headers可以是一個(gè)列表或字典,作為額外的消息標(biāo)頭值。元組的形式是(響應(yīng)體,狀態(tài)碼,頭部信息),也不一定三個(gè)都要寫,寫兩個(gè)也是可以的。返回的元組,其實(shí)在底層也是包裝成了一個(gè)Response對(duì)象。 - 可以返回
Response及其子類。
10.2 實(shí)現(xiàn)一個(gè)自定義的Response對(duì)象
- 繼承自
Response類。 - 實(shí)現(xiàn)方法
force_type(cls,rv,environ=None)。 - 指定
app.response_class為你自定義的Response對(duì)象。 - 如果視圖函數(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ù)
-
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的常用屬性
-
methods
默認(rèn)的請(qǐng)求方式只有GET,其他請(qǐng)求都需要通過參數(shù)methods進(jìn)行指定。
methods=['GET', 'POST']
-
args:獲取GET請(qǐng)求參數(shù)
flask中,要獲取get請(qǐng)求的參數(shù),不是通過request.GET.get(),而是通過request.args.get()獲取。
request.agrs.get('參數(shù)名')
-
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))