1躺彬,F(xiàn)lask框架的誕生:
Flask誕生于2010年,是Armin ronacher(人名)用Python語(yǔ)言基于Werkzeug工具箱編寫的輕量級(jí)Web開發(fā)框架梅惯。它主要面向需求簡(jiǎn)單的小應(yīng)用宪拥。
Flask本身相當(dāng)于一個(gè)內(nèi)核,其他幾乎所有的功能都要用到擴(kuò)展(郵件擴(kuò)展Flask-Mail铣减,用戶認(rèn)證Flask-Login)她君,都需要用第三方的擴(kuò)展來(lái)實(shí)現(xiàn)。比如可以用Flask-extension加入ORM葫哗、窗體驗(yàn)證工具缔刹,文件上傳球涛、身份驗(yàn)證等。Flask沒(méi)有默認(rèn)使用的數(shù)據(jù)庫(kù)校镐,你可以選擇MySQL亿扁,也可以用NoSQL。其 WSGI 工具箱采用 Werkzeug(路由模塊) 鸟廓,模板引擎則使用 Jinja2 从祝。
可以說(shuō)Flask框架的核心就是Werkzeug和Jinja2。
Python最出名的框架要數(shù)Django引谜,此外還有Flask牍陌、Tornado等框架。
雖然Flask不是最出名的框架员咽,但是Flask應(yīng)該算是最靈活的框架之一毒涧,這也是Flask受到廣大開發(fā)者喜愛(ài)的原因。
2骏融,F(xiàn)lask部分?jǐn)U展包:
Flask-SQLalchemy:操作數(shù)據(jù)庫(kù)链嘀;
Flask-migrate:管理遷移數(shù)據(jù)庫(kù);
Flask-Mail:郵件档玻;
Flask-WTF:表單怀泊;
Flask-Bable:提供國(guó)際化和本地化支持,翻譯误趴;
Flask-script:插入腳本霹琼;
Flask-Login:認(rèn)證用戶狀態(tài);
Flask-OpenID:認(rèn)證凉当;
Flask-RESTful:開發(fā)REST API的工具枣申;
Flask-Bootstrap:集成前端Twitter Bootstrap框架;
Flask-Moment:本地化日期和時(shí)間看杭;
3忠藤,F(xiàn)lask參考網(wǎng)站
中文文檔(http://docs.jinkan.org/docs/flask/)
英文文檔(http://flask.pocoo.org/docs/0.11/)
4,第一個(gè)Hello Flask程序
Flask程序運(yùn)行過(guò)程:
所有Flask程序必須有一個(gè)程序?qū)嵗?/p>
Flask調(diào)用視圖函數(shù)后楼雹,會(huì)將視圖函數(shù)的返回值作為響應(yīng)的內(nèi)容模孩,返回給客戶端。
一般情況下贮缅,響應(yīng)內(nèi)容主要是字符串和狀態(tài)碼榨咐。
當(dāng)客戶端想要獲取資源時(shí),一般會(huì)通過(guò)瀏覽器發(fā)起HTTP請(qǐng)求谴供。
此時(shí)块茁,Web服務(wù)器使用WSGI(Web Server Gateway Interface)協(xié)議,把來(lái)自客戶端的所有請(qǐng)求都交給Flask程序?qū)嵗绦驅(qū)嵗褂肳erkzeug來(lái)做路由分發(fā)(URL請(qǐng)求和視圖函數(shù)之間的對(duì)應(yīng)關(guān)系)数焊。
根據(jù)每個(gè)URL請(qǐng)求永淌,找到具體的視圖函數(shù)。
在Flask程序中昌跌,路由的實(shí)現(xiàn)一般是通過(guò)程序?qū)嵗难b飾器實(shí)現(xiàn)仰禀。
通過(guò)調(diào)用視圖函數(shù),獲取到數(shù)據(jù)后蚕愤,把數(shù)據(jù)傳入HTML模板文件中,模板引擎負(fù)責(zé)渲染HTTP響應(yīng)數(shù)據(jù)饺蚊,然后由Flask返回響應(yīng)數(shù)據(jù)給瀏覽器萍诱,最后瀏覽器處理返回的結(jié)果顯示給客戶端。
示例:
#導(dǎo)入Flask類
from flask import Flask
#Flask函數(shù)接收一個(gè)參數(shù)name污呼,它會(huì)指向程序所在的模塊
'''
注意:name可以傳入的參數(shù):
1裕坊,字符串:‘hello’,但是‘a(chǎn)bc’,不行,因?yàn)閍bc是python內(nèi)置的模塊
2燕酷,__name__
不可以插入的參數(shù)
1籍凝,python內(nèi)置的模塊,re,urllib,abc等
2苗缩,數(shù)字
'''
app = Flask(__name__)
#裝飾器的作用是將路由映射到視圖函數(shù)index
@app.route('/')
def index():
return 'Hello Flask'
#Flask應(yīng)用程序?qū)嵗膔un方法啟動(dòng)WEB服務(wù)器
if __name__ == '__main__':
app.run()
5,默認(rèn)的URL和正則URL
@app.route('<URL>')中URL顯式支持string饵蒂、int、float酱讶、path 4種類型退盯,隱式支持正則
5.1默認(rèn)的url
分析源碼(在routing.py文件中,大概1092行中)發(fā)現(xiàn)url支持以下幾種類型
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
5.2正則URL的實(shí)現(xiàn)
第一步泻肯,寫正則類渊迁,繼承BaseConverter,將匹配到的值設(shè)置為regex的值就可以了
class RegexUrl(BaseConverter):
def __init__(self, url_map, *args):
super(RegexUrl, self).__init__(url_map)
self.regex = args[0]
第二步,把正則類賦值給我們定義的正則規(guī)則
app.url_map.converters['re'] = RegexUrl
第三步灶挟,在URL中使用正則
@app.route('/regex/<re("[a-z]{3}"):id>')
def regex(id):
return 'id:%s'%id
6,Flask中鉤子的理解和應(yīng)用
鉤子是通過(guò)裝飾器的形式實(shí)現(xiàn)的琉朽,支持以下四種
- before_first_request:在處理第一個(gè)請(qǐng)求前運(yùn)行
- before_request:在每次請(qǐng)求前運(yùn)行
- after_request:如果沒(méi)有未處理的異常拋出,在每次請(qǐng)求后運(yùn)行
- teardown_request:即使有未處理的異常拋出稚铣,在每次請(qǐng)求后運(yùn)行
應(yīng)用:
@api.after_request
def after_request(response):
"""設(shè)置默認(rèn)的響應(yīng)報(bào)文格式為application/json"""
# 如果響應(yīng)報(bào)文response的Content-Type是以text開頭箱叁,則將其改為默認(rèn)的json類型
if response.headers.get("Content-Type").startswith("text"):
response.headers["Content-Type"] = "application/json"
return response
7,自定義過(guò)濾器的步驟如下:
第一步:先定義自定義過(guò)濾器函數(shù)
def count_substring(string, substring):
return string.count(substring)
第二步:注冊(cè)自己定義的過(guò)濾器
app.jinja_env.filters['count_substring'] = count_substring
第三步:最后在模板文件html中直接使用注冊(cè)時(shí)的鍵名
{#前面的作為原字符串string,傳入的作為子字符串substring#}
{{ 'A long long long long long long longabc string ' | count_substring('long') }}<br/>
8榛泛,什么是Werkzeug蝌蹂?
Werkzeug是WSGI協(xié)議層工具集。
WSGI本身是一個(gè)用來(lái)確保你的web應(yīng)用能夠與webserver進(jìn)行對(duì)話曹锨,
更重要的是孤个,確保web應(yīng)用之間能夠一起配合工作的協(xié)議或約定。
在沒(méi)有Werkzeug幫助下沛简,用WSGI實(shí)現(xiàn)的一個(gè)基本“Hello World”應(yīng)用看起來(lái)是這樣的:
def application(environ, start_response):
start_response(‘200 OK’, [(‘Content-Type’, ‘text/plain’)])
return [‘Hello World!’]
WSGI應(yīng)用是你可以調(diào)用齐鲤、傳遞一個(gè)environ字典和一個(gè)start_response函數(shù)的東西斥废。
environ包含所有的傳入信息,start_response函數(shù)可以用來(lái)指示response的開始给郊。
使用Werkzeug之后牡肉,你將不再需要直接處理被提交上來(lái)的請(qǐng)求(request)和應(yīng)答(response)對(duì)象。
請(qǐng)求數(shù)據(jù)獲取environ對(duì)象淆九,并允許你以一種良好的方式訪問(wèn)environ中的數(shù)據(jù)统锤。
response對(duì)象本身也是一個(gè)WSGI應(yīng)用,提供了很多友好的創(chuàng)建response的方法炭庙。
下面的代碼演示了如何編寫帶有response對(duì)象的應(yīng)用:
from werkzeug.wrappers import Response
def application(environ, start_response):
response = Response(‘Hello World!’, mimetype=‘text/plain’)
return response(environ, start_response)
9饲窿,flask-script指令第三方擴(kuò)展
第一種——?jiǎng)?chuàng)建Command子類
Command子類必須定義一個(gè)run方法;
舉例:創(chuàng)建Hello命令焕蹄,并將Hello命令加入Manager實(shí)例
from flask_script import Manager
from flask_script import Command
from debug import app
manager = Manager(app)
class Hello(Command):
'hello world'
def run(self):
print 'hello world'
manager.add_command('hello', Hello())
def make_shell_context():
return dict(app = app, db=db)
manager.add_command("shell",Shell(make_context=make_shell_context))
if __name__ == '__main__':
manager.run()
第二種——使用Command實(shí)例的@command修飾符
from flask_script import Manager
from debug import app
manager = Manager(app)
@manager.command
def hello():
'hello world'
print 'hello world'
if __name__ == '__main__':
manager.run()
第三種——使用Command實(shí)例的@option修飾符
復(fù)雜情況下逾雄,建議使用@option;
可以有多個(gè)@option選項(xiàng)參數(shù)
10,請(qǐng)求上下文和應(yīng)用上下文的區(qū)別
current_app腻脏、g就是應(yīng)用上下文
requests鸦泳、session就是請(qǐng)求上下文
手動(dòng)創(chuàng)建上下文的兩種方法:
with app.app_context()
app = current_app._get_current_object()
11,Flask特有的變量和函數(shù)
config
你可以從模板中直接訪問(wèn)Flask當(dāng)前的config對(duì)象:
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:xiaoke@127.0.0.1:3306/test'
request:
就是flask中代表當(dāng)前請(qǐng)求的request對(duì)象:
http://127.0.0.1
session
為Flask的session對(duì)象
注意:
flask中有三個(gè)session:
第一個(gè):數(shù)據(jù)庫(kù)中的session,例如:db.session.add()
第二個(gè):在flask_session擴(kuò)展中的session永品,使用:from flask_session import Session做鹰,使用第三方擴(kuò)展的session可以把信息存儲(chǔ)在服務(wù)器中,客戶端瀏覽器中只存儲(chǔ)sessionid
第三個(gè):flask自帶的session腐碱,是一個(gè)請(qǐng)求上下文誊垢, 使用:from flask import session。自帶的session把信息加密后都存儲(chǔ)在客戶端的瀏覽器cookie中
url_for()
url_for會(huì)根據(jù)傳入的路由器函數(shù)名,返回該路由對(duì)應(yīng)的URL,在模板中始終使用url_for()就可以安全的修改路由綁定的URL,則不比擔(dān)心模板中渲染出錯(cuò)的鏈接:
{ {url_for('home')} }
如果我們定義的路由URL是帶有參數(shù)的,則可以把它們作為關(guān)鍵字參數(shù)傳入url_for(),Flask 會(huì)把他們填充進(jìn)最終生成的URL中:
{ { url_for('post', post_id=1)} }
/post/1
get_flashed_messages()
這個(gè)函數(shù)會(huì)返回之前在flask中通過(guò)flash()傳入的消息的列表,
flash函數(shù)的作用很簡(jiǎn)單,可以把由Python字符串表示的消息加入一個(gè)消息隊(duì)列中,再使用get_flashed_messages()函數(shù)取出它們并消費(fèi)掉:
{ %for message in get_flashed_messages()% }
message
{ %endfor% }