1,Flask框架的誕生:
Flask誕生于2010年,是Armin ronacher(人名)用Python語言基于Werkzeug工具箱編寫的輕量級Web開發框架。它主要面向需求簡單的小應用。
Flask本身相當于一個內核,其他幾乎所有的功能都要用到擴展(郵件擴展Flask-Mail,用戶認證Flask-Login),都需要用第三方的擴展來實現。比如可以用Flask-extension加入ORM、窗體驗證工具,文件上傳、身份驗證等。Flask沒有默認使用的數據庫,你可以選擇MySQL,也可以用NoSQL。其 WSGI 工具箱采用 Werkzeug(路由模塊) ,模板引擎則使用 Jinja2 。
可以說Flask框架的核心就是Werkzeug和Jinja2。
Python最出名的框架要數Django,此外還有Flask、Tornado等框架。
雖然Flask不是最出名的框架,但是Flask應該算是最靈活的框架之一,這也是Flask受到廣大開發者喜愛的原因。
2,Flask部分擴展包:
Flask-SQLalchemy:操作數據庫;
Flask-migrate:管理遷移數據庫;
Flask-Mail:郵件;
Flask-WTF:表單;
Flask-Bable:提供國際化和本地化支持,翻譯;
Flask-script:插入腳本;
Flask-Login:認證用戶狀態;
Flask-OpenID:認證;
Flask-RESTful:開發REST API的工具;
Flask-Bootstrap:集成前端Twitter Bootstrap框架;
Flask-Moment:本地化日期和時間;
3,Flask參考網站
中文文檔(http://docs.jinkan.org/docs/flask/)
英文文檔(http://flask.pocoo.org/docs/0.11/)
4,第一個Hello Flask程序
Flask程序運行過程:
所有Flask程序必須有一個程序實例。
Flask調用視圖函數后,會將視圖函數的返回值作為響應的內容,返回給客戶端。
一般情況下,響應內容主要是字符串和狀態碼。
當客戶端想要獲取資源時,一般會通過瀏覽器發起HTTP請求。
此時,Web服務器使用WSGI(Web Server Gateway Interface)協議,把來自客戶端的所有請求都交給Flask程序實例,程序實例使用Werkzeug來做路由分發(URL請求和視圖函數之間的對應關系)。
根據每個URL請求,找到具體的視圖函數。
在Flask程序中,路由的實現一般是通過程序實例的裝飾器實現。
通過調用視圖函數,獲取到數據后,把數據傳入HTML模板文件中,模板引擎負責渲染HTTP響應數據,然后由Flask返回響應數據給瀏覽器,最后瀏覽器處理返回的結果顯示給客戶端。
示例:
#導入Flask類
from flask import Flask
#Flask函數接收一個參數name,它會指向程序所在的模塊
'''
注意:name可以傳入的參數:
1,字符串:‘hello’,但是‘abc’,不行,因為abc是python內置的模塊
2,__name__
不可以插入的參數
1,python內置的模塊,re,urllib,abc等
2,數字
'''
app = Flask(__name__)
#裝飾器的作用是將路由映射到視圖函數index
@app.route('/')
def index():
return 'Hello Flask'
#Flask應用程序實例的run方法啟動WEB服務器
if __name__ == '__main__':
app.run()
5,默認的URL和正則URL
@app.route('<URL>')中URL顯式支持string、int、float、path 4種類型,隱式支持正則
5.1默認的url
分析源碼(在routing.py文件中,大概1092行中)發現url支持以下幾種類型
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
5.2正則URL的實現
第一步,寫正則類,繼承BaseConverter,將匹配到的值設置為regex的值就可以了
class RegexUrl(BaseConverter):
def __init__(self, url_map, *args):
super(RegexUrl, self).__init__(url_map)
self.regex = args[0]
第二步,把正則類賦值給我們定義的正則規則
app.url_map.converters['re'] = RegexUrl
第三步,在URL中使用正則
@app.route('/regex/<re("[a-z]{3}"):id>')
def regex(id):
return 'id:%s'%id
6,Flask中鉤子的理解和應用
鉤子是通過裝飾器的形式實現的,支持以下四種
- before_first_request:在處理第一個請求前運行
- before_request:在每次請求前運行
- after_request:如果沒有未處理的異常拋出,在每次請求后運行
- teardown_request:即使有未處理的異常拋出,在每次請求后運行
應用:
@api.after_request
def after_request(response):
"""設置默認的響應報文格式為application/json"""
# 如果響應報文response的Content-Type是以text開頭,則將其改為默認的json類型
if response.headers.get("Content-Type").startswith("text"):
response.headers["Content-Type"] = "application/json"
return response
7,自定義過濾器的步驟如下:
第一步:先定義自定義過濾器函數
def count_substring(string, substring):
return string.count(substring)
第二步:注冊自己定義的過濾器
app.jinja_env.filters['count_substring'] = count_substring
第三步:最后在模板文件html中直接使用注冊時的鍵名
{#前面的作為原字符串string,傳入的作為子字符串substring#}
{{ 'A long long long long long long longabc string ' | count_substring('long') }}<br/>
8,什么是Werkzeug?
Werkzeug是WSGI協議層工具集。
WSGI本身是一個用來確保你的web應用能夠與webserver進行對話,
更重要的是,確保web應用之間能夠一起配合工作的協議或約定。
在沒有Werkzeug幫助下,用WSGI實現的一個基本“Hello World”應用看起來是這樣的:
def application(environ, start_response):
start_response(‘200 OK’, [(‘Content-Type’, ‘text/plain’)])
return [‘Hello World!’]
WSGI應用是你可以調用、傳遞一個environ字典和一個start_response函數的東西。
environ包含所有的傳入信息,start_response函數可以用來指示response的開始。
使用Werkzeug之后,你將不再需要直接處理被提交上來的請求(request)和應答(response)對象。
請求數據獲取environ對象,并允許你以一種良好的方式訪問environ中的數據。
response對象本身也是一個WSGI應用,提供了很多友好的創建response的方法。
下面的代碼演示了如何編寫帶有response對象的應用:
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指令第三方擴展
第一種——創建Command子類
Command子類必須定義一個run方法;
舉例:創建Hello命令,并將Hello命令加入Manager實例
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實例的@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實例的@option修飾符
復雜情況下,建議使用@option;
可以有多個@option選項參數
10,請求上下文和應用上下文的區別
current_app、g就是應用上下文
requests、session就是請求上下文
手動創建上下文的兩種方法:
with app.app_context()
app = current_app._get_current_object()
11,Flask特有的變量和函數
config
你可以從模板中直接訪問Flask當前的config對象:
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:xiaoke@127.0.0.1:3306/test'
request:
就是flask中代表當前請求的request對象:
http://127.0.0.1
session
為Flask的session對象
注意:
flask中有三個session:
第一個:數據庫中的session,例如:db.session.add()
第二個:在flask_session擴展中的session,使用:from flask_session import Session,使用第三方擴展的session可以把信息存儲在服務器中,客戶端瀏覽器中只存儲sessionid
第三個:flask自帶的session,是一個請求上下文, 使用:from flask import session。自帶的session把信息加密后都存儲在客戶端的瀏覽器cookie中
url_for()
url_for會根據傳入的路由器函數名,返回該路由對應的URL,在模板中始終使用url_for()就可以安全的修改路由綁定的URL,則不比擔心模板中渲染出錯的鏈接:
{ {url_for('home')} }
如果我們定義的路由URL是帶有參數的,則可以把它們作為關鍵字參數傳入url_for(),Flask 會把他們填充進最終生成的URL中:
{ { url_for('post', post_id=1)} }
/post/1
get_flashed_messages()
這個函數會返回之前在flask中通過flash()傳入的消息的列表,
flash函數的作用很簡單,可以把由Python字符串表示的消息加入一個消息隊列中,再使用get_flashed_messages()函數取出它們并消費掉:
{ %for message in get_flashed_messages()% }
message
{ %endfor% }