Flask框架知識(shí)系列之一

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)的琉朽,支持以下四種

  1. before_first_request:在處理第一個(gè)請(qǐng)求前運(yùn)行
  2. before_request:在每次請(qǐng)求前運(yùn)行
  3. after_request:如果沒(méi)有未處理的異常拋出,在每次請(qǐng)求后運(yùn)行
  4. 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% }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末症见,一起剝皮案震驚了整個(gè)濱河市喂走,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谋作,老刑警劉巖芋肠,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異遵蚜,居然都是意外死亡帖池,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門吭净,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)睡汹,“玉大人,你說(shuō)我怎么就攤上這事寂殉∏舭停” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)彤叉。 經(jīng)常有香客問(wèn)我庶柿,道長(zhǎng),這世上最難降的妖魔是什么秽浇? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任浮庐,我火速辦了婚禮,結(jié)果婚禮上柬焕,老公的妹妹穿的比我還像新娘审残。我一直安慰自己,他們只是感情好斑举,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布维苔。 她就那樣靜靜地躺著,像睡著了一般懂昂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上没宾,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天凌彬,我揣著相機(jī)與錄音,去河邊找鬼循衰。 笑死铲敛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的会钝。 我是一名探鬼主播伐蒋,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼迁酸!你這毒婦竟也來(lái)了轧邪?” 一聲冷哼從身側(cè)響起荚守,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后檬某,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡裹匙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年疯攒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澡罚。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡伸但,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出留搔,到底是詐尸還是另有隱情更胖,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站函喉,受9級(jí)特大地震影響避归,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜管呵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一梳毙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捐下,春花似錦账锹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至婴程,卻和暖如春廓奕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背档叔。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工桌粉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衙四。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓铃肯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親传蹈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子押逼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容