flask入門(URL)
lask自2010年發(fā)布第一個版本以來,大受歡迎,深得開發(fā)者的喜愛,并且在多個公司已經(jīng)得到了應(yīng)用,flask能如此流行的原因,可以分為以下幾點:
微框架、簡潔、只做他需要做的,給開發(fā)展提供了很大的擴展性。
Flask和相關(guān)的依賴(Jinja2、Werkzeug)設(shè)計得非常優(yōu)秀,用起來很爽。
開發(fā)效率非常高,比如使用SQLAlchemy的ORM操作數(shù)據(jù)庫可以節(jié)省開發(fā)者大量書寫sql的時間。
社會活躍度非常高。
Python學習交流 330637182 群內(nèi)每天更新相關(guān)資料
Flask的靈活度非常之高,他不會幫你做太多的決策,即使做已經(jīng)幫你做出選擇,你也能非常容易的更換成你需要的,比如:
使用Flask開發(fā)數(shù)據(jù)庫的時候,具體是使用SQLAlchemy還是MongoEngine或者是不用ORM而直接基于MySQL-Python這樣的底層驅(qū)動進行開發(fā)都是可以的,選擇權(quán)完全掌握在你自己的手中。區(qū)別于Django,Django內(nèi)置了非常完善和豐富的功能,并且如果你想替換成你自己想要的,要么不支持,要么非常麻煩。
把默認的Jinija2模板引擎替換成Mako引擎或者是其他模板引擎都是非常容易的。
第一個flask程序:
用pycharm新建一個flask項目,新建項目的截圖如下: 點擊create后創(chuàng)建一個新項目,然后在helloworld.py文件中書寫代碼:
#coding: utf8
# 從flask框架中導入Flask類
from flask import Flask
# 傳入__name__初始化一個Flask實例
app = Flask(__name__)
# app.route裝飾器映射URL和執(zhí)行的函數(shù)。這個設(shè)置將根URL映射到了hello_world函數(shù)上
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
# 運行本項目,host=0.0.0.0可以讓其他電腦也能訪問到該網(wǎng)站,port指定訪問的端口。默認的host是127.0.0.1,port為5000
app.run(host='0.0.0.0',port=9000)
然后點擊運行,在瀏覽器中輸入http://127.0.0.1:9000就能看到hello world了。需要說明一點的是,app.run這種方式只適合于開發(fā),如果在生產(chǎn)環(huán)境中,應(yīng)該使用Gunicorn或者uWSGI來啟動。如果是在終端運行的,可以按ctrl+c來讓服務(wù)停止。
Python學習交流 330637182 群內(nèi)每天更新相關(guān)資料
設(shè)置為DEBUG模式:
默認情況下flask不會開啟DEBUG模式,開啟DEBUG模式后,flask會在每次保存代碼的時候自動的重新載入代碼,并且如果代碼有錯誤,會在終端進行提示。
開啟DEBUG模式有三種方式:
直接在應(yīng)用對象上設(shè)置:
app.debug = True
app.run()
在執(zhí)行run方法的時候,傳遞參數(shù)進去:
app.run(debug=True)
在config屬性中設(shè)置:
app.config.update(DEBUG=True)
如果一切正常,會在終端打印以下信息:
* Restarting with stat
* Debugger is active!
* Debugger pin code: 294-745-044
* Running on http://0.0.0.0:9000/ (Press CTRL+C to quit)
需要注意的是,只能在開發(fā)環(huán)境下開啟DEBUG模式,因為DEBUG模式會帶來非常大的安全隱患。
另外,在開啟了DEBUG模式后,當程序有異常而進入錯誤堆棧模式,你第一次點擊某個堆棧想查看變量值的時候,頁面會彈出一個對話框,讓你輸入PIN值,這個PIN值在你啟動的時候就會出現(xiàn),比如在剛剛啟動的項目中的PIN值為294-745-044,你輸入這個值后,Werkzeug會把這個PIN值作為cookie的一部分保存起來,并在8小時候過期,8小時以內(nèi)不需要再輸入PIN值。這樣做的目的是為了更加的安全,讓調(diào)試模式下的攻擊者更難攻擊到本站。
Python學習交流 330637182 群內(nèi)每天更新相關(guān)資料
項目配置:
Flask項目的配置,都是通過app.config對象來進行配置的。比如要配置一個項目處于DEBUG模式下,那么可以使用app.config['DEBUG] = True來進行設(shè)置,那么Flask項目將以DEBUG模式運行。在Flask項目中,有四種方式進行項目的配置:
直接硬編碼:
app = Flask(__name__)
app.config['DEBUG'] = True
因為app.config是flask.config.Config的實例,而Config類是繼承自dict,因此可以通過update方法:
app.config.update(
DEBUG=True,
SECRET_KEY='...'
)
如果你的配置項特別多,你可以把所有的配置項都放在一個模塊中,然后通過加載模塊的方式進行配置,假設(shè)有一個settings.py模塊,專門用來存儲配置項的,此時你可以通過app.config.from_object()方法進行加載,并且該方法既可以接收模塊的的字符串名稱,也可以模塊對象:
# 1. 通過模塊字符串
app.config.from_object('settings')
# 2. 通過模塊對象
import settings
app.config.from_object(settings)
也可以通過另外一個方法加載,該方法就是app.config.from_pyfile(),該方法傳入一個文件名,通常是以.py結(jié)尾的文件,但也不限于只使用.py后綴的文件:
app.config.from_pyfile('settings.py',silent=True)
# silent=True表示如果配置文件不存在的時候不拋出異常,默認是為False,會拋出異常。
Flask項目內(nèi)置了許多的配置項,所有的內(nèi)置配置項,可以在這里查看。
Python學習交流 330637182 群內(nèi)每天更新相關(guān)資料
URL與函數(shù)的映射:
從之前的helloworld.py文件中,我們已經(jīng)看到,一個URL要與執(zhí)行函數(shù)進行映射,使用的是@app.route裝飾器。@app.route裝飾器中,可以指定URL的規(guī)則來進行更加詳細的映射,比如現(xiàn)在要映射一個文章詳情的URL,文章詳情的URL是/article/id/,id有可能為1、2、3...,那么可以通過以下方式: python @app.route('/article/ string: 默認的數(shù)據(jù)類型,接受沒有任何斜杠“/”的文本。 int: 接受整形。 float: 接受浮點類型。 path: 和string的類似,但是接受斜杠。 uuid: 只接受uuid字符串。 any:可以指定多種路徑,這個通過一個例子來進行說明: @app.route('/ def item(url_path): return url_path 以上例子中,item這個函數(shù)可以接受兩個URL,一個是/article/,另一個是/blog/。并且,一定要傳url_path參數(shù),當然這個url_path的名稱可以隨便。 如果不想定制子路徑來傳遞參數(shù),也可以通過傳統(tǒng)的?=的形式來傳遞參數(shù),例如:/article?id=xxx,這種情況下,可以通過request.args.get('id')來獲取id的值。如果是post方法,則可以通過request.form.get('id')來進行獲取。 構(gòu)造URL(url_for): 一般我們通過一個URL就可以執(zhí)行到某一個函數(shù)。如果反過來,我們知道一個函數(shù),怎么去獲得這個URL呢?url_for函數(shù)就可以幫我們實現(xiàn)這個功能。url_for()函數(shù)接收兩個及以上的參數(shù),他接收函數(shù)名作為第一個參數(shù),接收對應(yīng)URL規(guī)則的命名參數(shù),如果還出現(xiàn)其他的參數(shù),則會添加到URL的后面作為查詢參數(shù)。 通過構(gòu)建URL的方式而選擇直接在代碼中拼URL的原因有兩點: 將來如果修改了URL,但沒有修改該URL對應(yīng)的函數(shù)名,就不用到處去替換URL了。 url_for()函數(shù)會轉(zhuǎn)義特殊字符和Unocode數(shù)據(jù),這些工作都不需要我們自己處理。 下面用一個例子來進行解釋: ```python from flask import Flask,url_for app = Flask(name) @app.route('/article/ def article(id): return '%s article detail' % id # 這行的代碼可以在交互模式下產(chǎn)生請求上下文,不用`app.run()`來運行這個項目,直接可以運行下面的代碼, # 也會有`flask`上下文 with app.test_request_context(): print url_for('article',id='1') print url_for('article',id='2',next='/') ``` 執(zhí)行后的結(jié)果如下: > /article/1/ > /article/2/?next=%2F 自定義URL轉(zhuǎn)換器: 剛剛在URL映射的時候,我們看到了Flask內(nèi)置了幾種數(shù)據(jù)類型的轉(zhuǎn)換器,比如有int/string等。如果Flask內(nèi)置的轉(zhuǎn)換器不能滿足你的需求,此時你可以自定義轉(zhuǎn)換器。自定義轉(zhuǎn)換器,需要滿足以下幾個條件: 轉(zhuǎn)換器是一個類,且必須繼承自werkzeug.routing.BaseConverter。 在轉(zhuǎn)換器類中,必須實現(xiàn)to_python(self,value)方法,這個方法的返回值,將會傳遞到view函數(shù)中作為參數(shù)。 在轉(zhuǎn)換器類中,必須實現(xiàn)to_url(self,values)方法,這個方法的返回值,將會在調(diào)用url_for函數(shù)的時候生成符合要求的URL形式。 比如,拿一個官方的例子來說,Reddit可以通過在URL中用一個加號(+)隔開社區(qū)的名字,方便同時查看來自多個社區(qū)的帖子。比如訪問“www.reddit.com/r/flask+lisp/”的時候,就同時可以查看flask和lisp兩個社區(qū)的帖子,現(xiàn)在我們自定義一個轉(zhuǎn)換器來實現(xiàn)這個功能: #coding: utf8 from flask import Flask,url_for from werkzeug.routing import BaseConverter class ListConverter(BaseConverter): def __init__(self,url_map,separator='+'): super(ListConverter,self).__init__(url_map) self.separator = separator def to_python(self, value): return value.split(self.separator) def to_url(self, values): return self.separator.join(BaseConverter.to_url(self,value) for value in values) @app.route('/community1/ def community1(page_names): return '%s+%s' % tuple(page_names) @app.route('/community2/ def community2(page_names): return '%s|%s' % tuple(page_names) communityu1使用的是默認的+號進行連接,而第二種方式使用了|進行連接。 URL唯一: Flask的URL規(guī)則是基于Werkzeug的路由模塊。這個模塊的思想是基于Apache以及更早的HTTP服務(wù)器的主張,希望保證優(yōu)雅且唯一的URL。 舉個例子: @app.route('/projects/') def projects(): return 'project page' 上述例子中,當訪問一個結(jié)尾不帶斜線的URL會被重定向到帶斜線的URL上去。這樣有助于避免搜索引擎搜索同一個頁面兩次。 再看一個例子: @app.route('/about') def about(): return 'about page' 以上例子中,當訪問帶斜線的URL(/about/)會產(chǎn)生一個404('Not Found')錯誤。 指定HTTP方法: 在@app.route()中可以傳入一個關(guān)鍵字參數(shù)methods來指定本方法支持的HTTP方法,默認只響應(yīng)GET請求,看以下例子: python @app.route('/login/',methods=['GET','POST']) def login(): return 'login' 以上裝飾器將讓login的URL既能支持GET又能支持POST。 頁面跳轉(zhuǎn)和重定向: 重定向分為永久性重定向和暫時性重定向,在頁面上體現(xiàn)的操作就是瀏覽器會從一個頁面自動跳轉(zhuǎn)到另外一個頁面。比如用戶訪問了一個需要權(quán)限的頁面,但是該用戶當前并沒有登錄,因此我們應(yīng)該給他重定向到登錄頁面。 永久性重定向: http的狀態(tài)碼是301,多用于舊網(wǎng)址被廢棄了要轉(zhuǎn)到一個新的網(wǎng)址確保用戶的訪問,最經(jīng)典的就是京東網(wǎng)站,你輸入www.jingdong.com的時候,會被重定向到www.jd.com,因為jingdong.com這個網(wǎng)址已經(jīng)被廢棄了,被改成jd.com,所以這種情況下應(yīng)該用永久重定向。 暫時性重定向: http的狀態(tài)碼是302,表示頁面的暫時性跳轉(zhuǎn)。比如訪問一個需要權(quán)限的網(wǎng)址,如果當前用戶沒有登錄,應(yīng)該重定向到登錄頁面,這種情況下,應(yīng)該用暫時性重定向。 在flask中,重定向是通過flask.redirect(location,code=302)這個函數(shù)來實現(xiàn)的,location表示需要重定向到的URL,應(yīng)該配合之前講的url_for()函數(shù)來使用,code表示采用哪個重定向,默認是302也即暫時性重定向,可以修改成301來實現(xiàn)永久性重定向。 以下來看一個例子,關(guān)于在flask中怎么使用重定向: from flask import Flask,url_for,redirect app = Flask(__name__) app.debug = True @app.route('/login/',methods=['GET','POST']) def login(): return 'login page' @app.route('/profile/',methods=['GET','POST']) def profile(): name = request.args.get('name') if not name: # 如果沒有name,說明沒有登錄,重定向到登錄頁面 return redirect() else: return name 關(guān)于響應(yīng)(Response): 視圖函數(shù)的返回值會被自動轉(zhuǎn)換為一個響應(yīng)對象,F(xiàn)lask的轉(zhuǎn)換邏輯如下: 如果返回的是一個合法的響應(yīng)對象,則直接返回。 如果返回的是一個字符串,那么Flask會重新創(chuàng)建一個werkzeug.wrappers.Response對象,Response將該字符串作為主體,狀態(tài)碼為200,MIME類型為text/html,然后返回該Response對象。 如果返回的是一個元組,元祖中的數(shù)據(jù)類型是(response,status,headers),只能包含一個元素。status值會覆蓋默認的200狀態(tài)碼,headers可以是一個列表或者字典,作為額外的消息頭。 如果以上條件都不滿足,F(xiàn)lask會假設(shè)返回值是一個合法的WSGIt應(yīng)用程序,并通過Response.force_type(rv,request.environ)轉(zhuǎn)換為一個請求對象。 以下將用例子來進行說明: 第一個例子:直接使用Response創(chuàng)建: from werkzeug.wrappers import Response @app.route('/about/') def about(): resp = Response(response='about page',status=200,content_type='text/html;charset=utf-8') return resp 第二個例子:可以使用make_response函數(shù)來創(chuàng)建Response對象,這個更加的方便,因為他封裝了默認的Content-Type以及status等: from flask import make_response @app.route('/about/') def about(): return make_response('about page') 第三個例子:通過返回元組的形式: @app.errorhandler(404) def not_found(): return 'not found',404 第四個例子:自定義響應(yīng)。自定義響應(yīng)必須滿足三個條件: 必須繼承自Response類。 必須實現(xiàn)類方法force_type(cls,rv,environ=None)。 必須指定app.response_class為你自定義的Response 以下將用一個例子來進行講解,Restful API都是通過JSON的形式進行傳遞,如果你的后臺跟前臺進行交互,所有的URL都是發(fā)送JSON數(shù)據(jù),那么此時你可以自定義一個叫做JSONResponse的類來代替Flask自帶的Response類: from flask import Flask,jsonify from werkzeug.wrappers import Response app = Flask(__name__) class JSONResponse(Response): default_mimetype = 'application/json' @classmethod def force_type(cls,response,environ=None): if isinstance(response,dict): response = jsonify(response) return super(JSONResponse,cls).force_type(response,environ) app.response_class = JSONResponse @app.route('/about/') def about(): return {'message':'about page'} if __name__ == '__main__': app.run(host='0.0.0.0',port=8000) 此時如果你訪問/about/這個URL,那么在頁面中將會顯示: { 'message': 'about page' }
Python學習交流 330637182 群內(nèi)每天更新相關(guān)資料/')
Python學習交流 330637182 群內(nèi)每天更新相關(guān)資料
聯(lián)系客服