Flask簡介
和Django大包大攬不同,Flask建立於一系列的開源軟體包之上,這其中最主要的是WSGI應用開發庫Werkzeug和模板引擎Jinja:
策略:werkzeug和Jinja這兩個函式庫和Flask一樣,都是pocoo團隊開發的。這 或許體現了pocoo與Django競爭時關於生態的一種策略,這種策略的自然 延伸是Flask框架中沒有包含資料庫方面的構件,無論ORM還是其他。
重點:Flask是一個WSGI應用框架,這表示我們進行Flask開發時,不需要專注於網路方面的操作,Flask應用程式的入口是封裝過的網路請求包,出口是網路回應,我們只需要關注這個階段內的處理邏輯。
WSGI伺服器 :Flask雖然內建了簡單的WSGI伺服器,但其效能僅適用於開發期間的偵錯。 Flask官網推薦了多種WSGI伺服器,實作方式從多進程到多執行緒到協程, 這方面的選擇我們在本課程中將不涉及。
REST適應性 :雖然Flask和Django一樣,最初的出發點都是服務端的動態網頁應用程式。但Flask的設計使其也相當適用於資源導向的REST架構,在越來越行動化且單頁應用越來越重要的WEB開發領域,這是Flask相對於Django相當大的優勢。
Hello Flask
寫一個基於Flask的hello world相當容易:
from flask import Flask
Flask類是Flask框架的核心類,它實作了WSGI應用規範。
app = Flask(name)
Flask建構子的第一個參數指定一個引入名/importname。 Flask框架 使用這個名字進行靜態資源、模板、錯誤訊息的定位。除非你清楚的理解它的 作用,通常情況下,我們總是應該使用特殊變數_name。
Flask實例是可呼叫的(具有call方法),這個實例可以直接對接 WSGI伺服器。
3、註冊路由
@route('/') def index(): return 'Hello,Flask!'
註冊路由就是建立URL規則和處理函數之間的關聯。 Flask框架依賴路由 完成HTTP請求的分發。
路由中的函數稱為視圖函數,其傳回值將作為HTTP回應的正文內容。
Flask封裝了一個簡單的開發用WSGI伺服器,我們可以透過呼叫run() 啟動伺服器來執行:
app.run(host='0.0.0.0',port=80)
概述
路由是MVC架構的Web框架中相當重要的概念,也是本課程的重點。
顧名思意,路由就是在迷茫中找出一條路的意思。在Flask框架中,路由就表示為使用者請求的URL找出其對應的處理函數之意。
在本節課程,我們將主要從以下幾個面向來講解Flask框架中的路由:
如何為應用程式註冊路由? 如何為路由指定其支援的HTTP方法? 如何匹配動態URL? 如何對URL中的變數類型進行篩選? 如何理解訪問點/endpoint? 如何為應用程式設定靜態路由? 如何避免硬編碼指向其他視圖的URL?
在Flask應用程式中,路由是指使用者請求的URL與視圖函數之間的對應。 Flask框架根據HTTP請求的URL在路由表中匹配預先定義的URL規則,找到對應的視圖函數, 並將視圖函數的執行結果傳回WSGI伺服器:
可見路由表在Flask應用中處於相當核心的位置。路由表的內容是由應用程式開發者填入。
route裝飾器 :可以使用Flask應用實例的route裝飾器將一個URL規則綁定到 一個視圖函數上。
例如,下面的範例將URL規則/test綁定到視圖函數test()上:
@app.route('/test') def test(): return 'this is response'
如果這個應用程式部署在主機ezhost.com的根目錄下,那麼當用戶訪問:
http://pythontab.com/teset
Flask框架就會呼叫我們的test()函數,其回傳結果就會傳遞給WSGI伺服器傳送給訪客。
add_url_rule() :另一個等價的寫法是使用Flask應用實例的add_url_route()方法。 下面的範例註冊了一個與前例相同的路由:
def test(): return 'this is response' app.add_url_route('/test',view_func=test)
其實,route裝飾器內部也是透過呼叫add_url_route()方法實現的路由註冊。 但顯然,使用裝飾器使程式碼看起來更優雅一些。
默认情况下,Flask路由仅支持HTTP的GET请求。可以使用methods关键字参数,在注册 路由时显式地声明视图方法支持的HTTP方法。
例如,下面的示例将URL规则/auth绑定到视图函数v_auth(),这个路由仅支持POST方法:
@app.route('/auth',methods=['POST']) def v_auth():pass
关键字参数methods的类型为list,因此可以同时指定多种HTTP方法。
下面的示例中,使URL规则/user同时支持POST方法和GET方法:
@app.route('/user',methods=['POST','GET']) def v_users(): if request.method == 'GET': return ... # 返回用户列表 if request.method == 'POST' return ... #创建新用户
这个特性使Flask非常易于开发REST架构的后台服务,而不仅仅局限于传统的动态网页。
有时我们需要将同一类URL映射到同一个视图函数处理,比如,使用同一个视图函数 来显示不同用户的个人档案。我们希望以下的URL都可以分发到同一个视图函数:
在Flask中,可以将URL中的可变部分使用一对小括号<>声明为变量, 并为视图函数声明同名的参数:
@app.route('/user/') def v_user(uname): return '%s\'s Profile' % uname
在上面的示例中,URL规则中的
考虑下面的示例,我们希望通过HTTP共享文件夹/var/readonly中的文件:
/var
/readonly
/a.txt
/b.txt
/repo
/c.txt
/d.txt
简单思考一下就有答案了。我们可以构造URL规则/file/
@app.route('/file/') def v_file(fname): fullname = os.path.join('/var/readonly',fname) f = open(fullname) cnt = f.read() f.close() return cnt
测试结果表明,/file/a.txt和/file/b.txt都没有问题,但是/file/repo/c.txt和 /file/repo/d.txt却会失败。
这是因为,默认情况下,在URL规则中的变量被视为不包含/的字符串。/file/repo/c.txt 是没有办法匹配URL规则/file/
可以使用内置的path转换器告诉Flask框架改变这一默认行为。path转换器允许 规则匹配包含/的字符串:
@app.route('/file/')
在Flask中,转换器/converter用来对从URL中提取的变量进行预处理,这个过程 发生在调用视图函数之前。Flask预置了四种转换器:
string - 匹配不包含/的字符串,这是默认的转换器
path - 匹配包含/的字符串
int - 只有当URL中的变量是整型值时才匹配,并将变量转换为整型
float - 只有当URL中的变量是浮点值时才匹配,并将变量转换为浮点型
我们一直强调,路由的作用是根据请求的URL,找到对应的视图函数。这没错,但是在 Flask框架中,请求任务的分发并不是直接从用户请求的URL一步定位到视图函数, 两者之间隔着一个访问点/endpoint。
以下面的代码为例,我们看Flask怎样实现请求的分发:
@app.route('/home') def home():pass
在Flask内部使用两张表维护路由:
url_map :维护URL规则和endpoint的映射
view_functions :维护endpoint和视图函数的映射。
以用户访问URL/home为例,Flask将首先利用url_map找到所请求URL对应的 endpoint,即访问点home,然后再利用view_functions表查找home这个访问点 对应的视图函数,最终匹配到函数home():
默认访问点 :当我们使用route装饰器注册路由时,默认使用被装饰函数的 函数名(name)作为访问点,因此,你看到上面的表中,路由中的访问点为home。
自定义访问点 :可以在使用route装饰器或调用add_url_rule()方法注册路由时,使用 endpoint关键字参数改变这一默认行为:
@app.route('/home',endpoint='whocare') def home():pass
此时的两张路由表将变成这样:
当创建应用实例时,Flask将自动添加一条静态目录路由,其访问点 始终被设置为static,URL规则默认被设置为/static,本地路径默认被 设置为应用文件夹下的static子文件夹:
+------------------------------------------------------------+ | url rule | endpoint | view_function | | /static | static | Flask.send_static_file | +------------------------------------------------------------+ 如果你的应用目录如下:
/app
/web.py
/static
/main.css
那么启动应用后就可以通过URL/static/main.css访问static文件夹下的main.css了。
除了访问点被固定为static,静态目录的URL规则和本地目录都是可以根据应用情况进行调整。
改变默认的本地路径 :可以在创建应用对象时使用关键字参数static_folder改变 默认的静态文件夹。例如,你的静态文件都存放在应用下的assets目录下, 那么可以按如下的方式创建应用对象:
app = Flask(name,static_folder='assets') 也可以使用一个绝对路径:
app = Flask(name,static_folder='/var/www/static') 改变默认的本地路径并不会对路由表产生影响。
改变默认的URL规则 : 如果不喜欢静态目录URL/static,也可以在创建应用 对象时使用关键字参数static_url_path换一个别的名字。
下面的示例中,将应用下的assets文件夹注册为静态目录/assets:
app = Flask(name,static_folder='assets',static_url_path='/assets') 当应用运行后,通过URL/assets/main.css就可以访问assets文件夹下的 main.css文件了。
这时的路由表变化为:
+------------------------------------------------------------+ | url | endpoint | view_function | | /assets | static | Flask.send_static_file | +------------------------------------------------------------+
在一个实用的视图中,不可避免地存在指向其他视图的链接。在之前的课程示例中,我们 都是在视图函数中这样硬编码这些链接URL的:
@app.route('/') def v_index(): return 'tech' @app.route('/tech') def v_tech():pass
大部分情况下这种硬编码URL是可以工作的。但如果这个应用被挂在WSGI服务器的一个 子路径下,比如:/app1,那么用户访问URL/tech是不会成功的,这时应当访问/app1/tech 才可以正确地路由到视图函数v_tech()。
我们应当使用访问点让Flask框架帮我们计算链接URL。简单地给url_for()函数传入 一个访问点,它返回将是一个可靠的URL地址:
@app.route('/') def v_index(): print url_for('v_contacts') # /contact return 'see console output!' @app.route('/contact') def v_contacts():pass
添加查询参数 : 使用关键字参数,可以在构造的URL中生成查询串。下面的调用将生成 /contact?
format=json @app.route('/') def v_index(): print url_for('v_contacts',format='json') return '' @app.route('/contact') def v_contacts():pass
添加URL变量 : 如果指定访问点对应的视图函数接收参数,那么关键字参数将生成对应的参数URL。下面的 示例将生成/contact/Julia?format=html:
@app.route('/') def v_index(): print url_for('v_contact',name='Julia',format='html') return '' @app.route('/contact/') def v_contact(name):pass
添加锚点 :使用_anchor关键字可以为生成的URL添加锚点。下面的示例将生成URL /contact#part2
@app.route('/') def v_index(): print url_for('v_contacts',_anchor='part2') @app.route('/contact') def v_contacts():pass
外部URL : 默认情况下,url_for()生成站内URL,可以设置关键字参数_external 为True,生成包含站点地址的外部URL。下面的示例将生成URLhttp://
@app.route('/') def v_index(): print url_for('v_contacts',_external=True) @app.route('/contact') def v_contacts():pass
以上是Python開發WEB框架Flask詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!