Flask目錄:http://www.reibang.com/p/9b5e30320849
路由
路由充當了一個指路牌的作用吮蛹,讓用戶訪問想要訪問的頁面得到想要的數(shù)據(jù)。
當然也可以多個頁面指向同一個路由(不過這樣肯定是有關聯(lián)的頁面拌屏,最好使用正則URL)
路由配置
Flask的路由配置是沒有專門的文件存放的潮针,基本是以裝飾器的形式存在視圖函數(shù)頂部。
實例:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
#路由裝飾器,語法為 app.route(url_name,methods)
#url_name:路由名
#methods:請求方式倚喂,默認get請求,可以使用列表指定多種方式每篷。例:['GET','POST']
@app.route('/index')
def hi_flask():
return 'Hi,Flask'
if __name__ == '__main__':
app.run()
同時,路由也有多種寫法:
參數(shù)傳遞:@app.route('/users/<username>')
指定類型:@app.route('/users/<int:pwd>')
一個簡單的傳參請求
實例:
from flask import Flask,url_for
app = Flask(__name__)
#使用參數(shù)接受url
@app.route('/user/<username>')
#給username設置一個默認值端圈,這樣不輸入username也可以訪問到這個頁面焦读。
def users(username=''):
return "用戶名:{}".format(username)
if __name__ == '__main__':
app.run()
同時還有另外一種方式,就是API方式枫笛。
實例:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
def hi_flask2():
return 'Hi,Flask2'
app.add_url_rule("/index2/", view_func=hi_flask2)
#API函數(shù)吨灭,第一個參數(shù)是路由名,第二個參數(shù)要以關鍵字參數(shù)傳入刑巧,值是一個配套的函數(shù)名喧兄。
if __name__ == '__main__':
app.run()
這兩種方式的詳解
首先我們從裝飾器入手:
源碼如下
-------
def route(self, rule, **options):
"""A decorator that is used to register a view function for a
given URL rule. This does the same thing as :meth:`add_url_rule`
but is intended for decorator usage::
@app.route('/')
def index():
return 'Hello World'
For more information refer to :ref:`url-route-registrations`.
:param rule: the URL rule as string
:param endpoint: the endpoint for the registered URL rule. Flask
itself assumes the name of the view function as
endpoint
:param options: the options to be forwarded to the underlying
:class:`~werkzeug.routing.Rule` object. A change
to Werkzeug is handling of method options. methods
is a list of methods this rule should be limited
to (``GET``, ``POST`` etc.). By default a rule
just listens for ``GET`` (and implicitly ``HEAD``).
Starting with Flask 0.6, ``OPTIONS`` is implicitly
added and handled by the standard request handling.
"""
def decorator(f):
endpoint = options.pop("endpoint", None)
self.add_url_rule(rule, endpoint, f, **options)
#這里調用了add_url_rule
return f
return decorator
也就是說,route只不過是封裝了一下的裝飾器啊楚,干活的還是add_url_rule吠冤。
這樣的話,大家直接用裝飾器就好了恭理。
路由反向解析
說到路由拯辙,就不能不能不說路由的反向解析,他可以幫助我們獲得用戶請求的路由與配套的視圖函數(shù)。
實例:
from flask import Flask,url_for
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
#路由裝飾器, 語法為 app.route(url_name,method) 前者是路由名涯保, 后者是請求方式诉濒,默認get請求
@app.route('/index')
def hi_flask():
return 'Hi,Flask'
def hi_flask2():
return 'Hi,Flask2'
app.add_url_rule("/index2/", view_func=hi_flask2)
#API函數(shù),第一個參數(shù)是路由名夕春,第二個參數(shù)要以關鍵字參數(shù)傳入未荒,值是一個配套的函數(shù)名。
# 查看URL規(guī)則
print(app.url_map)
# 反向解析及志,通過視圖名找到對應的路由
with app.test_request_context():
print(url_for('hello_world'))
print(url_for('hi_flask2'))
if __name__ == '__main__':
app.run()
輸出結果:
--------
Map([<Rule '/index2/' (GET, OPTIONS, HEAD) -> hi_flas2k>,
<Rule '/index' (GET, OPTIONS, HEAD) -> hi_flask>,
<Rule '/' (GET, OPTIONS, HEAD) -> hello_world>,
<Rule '/static/<filename>' (GET, OPTIONS, HEAD) -> static>])
/
/index2/
當然 url_for()還有很多其他的功能片排,以后會慢慢說。
請求與響應
上下文
上下文分為速侈,請求上下文與應用上下文率寡。用語文中的概念來理解即可。在計算機中倚搬,可以把它理解為環(huán)境冶共。
引用上下文
current_app:當前應用的案例
g:處理請求時的臨時存儲對象,每次請求都會重設這個對象
請求上下文
request:請求對象每界,封裝了客戶端發(fā)給服務端的HTTP請求
session:用戶會話比默,在各個會話中共享數(shù)據(jù)
請求
請求分派
我們來了一個請求'/index/',那么這個請求該去找哪個url規(guī)則呢盆犁,這個讓請求找到他目的地的過程就是請求分派。
請求報文常用參數(shù)
method:請求的方式(get篡九,post等等)
args:get請求提交的數(shù)據(jù)
form:form表單提交的數(shù)據(jù)
files:文件上傳
cookies:cookie的傳輸
headers:HTTP請求頭
GET請求
from flask import Flask,request
app = Flask(__name__)
@app.route('/user')
def users():
#request是獲取用戶請求對象谐岁,args是獲取用戶get請求數(shù)據(jù) 數(shù)據(jù)是dict類型。
get_dict = request.args
print(get_dict)
#從數(shù)據(jù)集中獲取某一個值榛臼。
username = request.args.get('username')
print(username)
#既然是dict類型伊佃,還是get方法,肯定能設置默認值啦沛善。
page = request.args.get('page',1)
print(page)
return "用戶名:{}".format(username)
if __name__ == '__main__':
app.run()
----------
輸出結果:
ImmutableMultiDict([('username', 'lisi')])
lisi
1
POST請求
在將模板操作時一起說鲁纠。
請求頭
headers是一個字典類型的數(shù)據(jù)竞膳,獲取后還可以通過get函數(shù)得到我們想要的數(shù)據(jù),例如請求的ip,系統(tǒng)平臺等等专酗。
from flask import Flask,request
app = Flask(__name__)
@app.route('/user')
def users():
headers = request.headers
return "請求頭:{}".format(headers)
if __name__ == '__main__':
app.run()
請求鉤子
請求鉤子就是用來校驗用戶請求舒服是否合法。有四個常用函數(shù)
- before_first_request
服務器初始化后第一個請求到達前執(zhí)行 - before_request
每一個請求到達前執(zhí)行 - after_request
每次請求處理完成后執(zhí)行呐馆,如果請求過程中產生了日常风科,則不執(zhí)行。 - teardown_request
每次請求處理完成后執(zhí)行产捞,如果請求過程中發(fā)生了異常也執(zhí)行醇锚。
實例1:
from flask import Flask,request
app = Flask(__name__)
@app.before_first_request
def first_req():
print('first_request')
print('------')
@app.before_request
def before_req():
print('brfore_request')
print('------')
@app.route('/user')
def users():
get_dict = request.args
print(get_dict)
print('------')
return "請求參數(shù):{}".format(get_dict)
if __name__ == '__main__':
app.run()
before_first_request函數(shù)確實只在確認連接的時候認證一次,而before_request會對每一次連接進行認證坯临。
實例2:
from flask import Flask,request
app = Flask(__name__)
@app.before_first_request
def first_req():
print('first_request')
print('------')
@app.before_request
def before_req():
print('brfore_request')
print('------')
@app.after_request
def after_req(resp):
print('after_request')
print('------')
return resp
@app.route('/user')
def users():
get_dict = request.args
print(get_dict)
print('------')
return "請求參數(shù):{}".format(get_dict)
if __name__ == '__main__':
app.run()
只要請求內部不報錯焊唬, after_request就會完美執(zhí)行恋昼。
teardown_request可以作為一個異常處理的方法,我們這里不探究他的使用赶促。
響應
我們處理完用戶的請求液肌,反饋給用戶的數(shù)據(jù)就是響應。響應可以是各種數(shù)據(jù)芳杏。其中特殊的包括我們反饋的數(shù)據(jù)矩屁,頁面,狀態(tài)碼和響應頭爵赵。
我們請求一個不存在的頁面吝秕,肯定會得到404的狀態(tài)碼。但是我們不想返回這個樸素的頁面空幻,這就需要我們的響應定制了烁峭。
from flask import Flask,request
app = Flask(__name__)
@app.errorhandler(404)
def not_fount(err):
print(err)
return '你要找的頁面找不到了'
if __name__ == '__main__':
app.run()
同時我們也可以修改一下返回的數(shù)據(jù),例如狀態(tài)碼或者headers秕铛。
@app.errorhandler(404)
def not_fount(err):
print(err)
return '你要找的頁面找不到了',404,{
'is_login':False
}
接著來看響應經常用到的方法:
make_response():相當于Django中的HttpResponse约郁。
from flask import Flask,make_response
app = Flask(__name__)
@app.route('/test')
def test():
make = make_response("<h1>這是一個測試頁面</h1>",200)
return make
if __name__ == '__main__':
app.run()
但是一般我們都是返回一個頁面的:
from flask import Flask,make_response,render_template
app = Flask(__name__)
@app.route('/test')
def test():
tmp = render_template('index.html')
make = make_response(tmp,200)
return make
if __name__ == '__main__':
app.run()
make_response 想要返回頁面,不能直接寫做:make_response('hello.html')但两,必須用render_template('hello.html')形式鬓梅。
重定向
redirect():相當于 Django中的HttpResponseRedirect。
from flask import Flask,make_response
app = Flask(__name__)
@app.route('/test')
def test():
make = make_response("<h1>這是一個測試頁面</h1>",200)
return make
@app.route('/test1')
def test1():
return redirect('/test')
if __name__ == '__main__':
app.run()
同時還有一個中止重定向的函數(shù):
abort()函數(shù)用于提前退出一個請求谨湘,并用指定的錯誤碼返回绽快。
from flask import Flask,make_response
app = Flask(__name__)
@app.route('/test')
def test():
make = make_response("<h1>這是一個測試頁面</h1>",200)
return make
@app.route('/test1')
def test1():
headers = request.headers
ip = headers.get('host')
print(ip)
ip_list = ['127.0.0.1:5000']
if ip in ip_list:
abort(403)
return redirect('/test')
if __name__ == '__main__':
app.run()
我們這里模仿了一個ip請求黑白名單的訪問。如果請求ip是我們的黑名單ip紧阔,就拋出一個403請求中斷當前請求坊罢。