### 導航
- [索引](# "總目錄")
- [下一頁](# "使用 WTForms 進行表單驗證") |
- [上一頁](# "緩存") |
- [Flask 0.10.1 文檔](#) ?
- [Flask 代碼模式](#) ?
# 視圖裝飾器
Python 擁有一件非常有趣的特性,那就是函數裝飾器。這個特性允許您使用一些非常簡介的語法編輯 Web 應用。因為 Flask 中的每個視圖都是一個函數裝飾器,這些裝飾器被用來將附加的功能注入到一個或者多個函數中。 [route()](# "flask.Flask.route")裝飾器您可能已經使用過了。但是在一些情況下您需要實現自己的裝飾器。例如,您有一個僅供登陸后的用戶訪問的視圖,如果未登錄的用戶試圖訪問,則把用戶轉接到登陸界面。這個例子很好地說明了裝飾器的用武之地。
### 過濾未登錄用戶的裝飾器
現在讓我們實現一個這樣的裝飾器。裝飾器是指返回函數的函數,它其實非常簡單。您僅需要記住,當實現一個類似的東西,其實是更新 __name__ 、 __module__以及函數的其他一些屬性,這件事情經常被遺忘。但是您不必親自動手,這里有一個專門用于處理這些的以裝飾器形式調用的函數([functools.wraps()](http://docs.python.org/dev/library/functools.html#functools.wraps "(在 Python v3.5)") [http://docs.python.org/dev/library/functools.html#functools.wraps] )。
這個例子家丁登陸頁面的名字是 'login' 并且當前用戶被保存在 g.user 當中,如果么有用戶登陸, g.user 會是 None:
~~~
from functools import wraps
from flask import g, request, redirect, url_for
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for('login', next=request.url))
return f(*args, **kwargs)
return decorated_function
~~~
所以您怎么使用這些裝飾器呢?將它加為視圖函數外最里層的裝飾器。當添加更多裝飾器的話,一定要記住 [route()](# "flask.Flask.route") 考試最外面的:
~~~
@app.route('/secret_page')
@login_required
def secret_page():
pass
~~~
### 緩存裝飾器
試想你有一個運算量很大的函數,而且您希望能夠將生成的結果在一段時間內緩存起來,一個裝飾器將會非常適合用于干這種事。我們假定您已經參考 [*緩存*](#)中提到的內容配置好了緩存功能。
這里有一個用作例子的緩存函數,它從一個指定的前綴(通常是一個格式化字符串)和當前請求的路徑生成一個緩存鍵。請注意我們創建了一個這樣的函數: 它先創建一個裝飾器,然后用這個裝飾器包裝目標函數。聽起來很復雜?不幸的是,這的確有些難,但是代碼看起來會非常直接明了。
被裝飾器包裝的函數將能做到如下幾點:
1. 以當前請求和路徑為基礎生成緩存時使用的鍵。
1. 從緩存中取出對應鍵的值,如果緩存返回的不是空,我們就將它返回回去。
1. 如果緩存中沒有這個鍵,那么最初的函數將會被執行,并且返回的值在指定時間(默認5分鐘內)被緩存起來。
代碼如下:
~~~
from functools import wraps
from flask import request
def cached(timeout=5 * 60, key='view/%s'):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = key % request.path
rv = cache.get(cache_key)
if rv is not None:
return rv
rv = f(*args, **kwargs)
cache.set(cache_key, rv, timeout=timeout)
return rv
return decorated_function
return decorator
~~~
注意,這段代碼假定一個示例用的 cache 對象時可用的。請參考 [*緩存*](#)以獲取更多信息。
### 模板裝飾器
TurboGears 的家伙們前一段時間發明了一種新的常用范式,那就是模板裝飾器。這個裝飾器的關鍵在于,您將想要傳遞給模板的值組織成字典的形式,然后從視圖函數中返回,這個模板將會被自動渲染。這樣,下面的三個例子就是等價的了:
~~~
@app.route('/')
def index():
return render_template('index.html', value=42)
@app.route('/')
@templated('index.html')
def index():
return dict(value=42)
@app.route('/')
@templated()
def index():
return dict(value=42)
~~~
正如您所看到的,如果沒有模板名被指定,那么他會使用 URL 映射的最后一部分,然后將點轉換為反斜杠,最后添加上 '.html' 作為模板的名字。當裝飾器包裝的函數返回,返回的字典就會被傳遞給模板渲染函數。如果 None 被返回了,那么相當于一個空的字典。如果非字典類型的對象被返回,函數將照原樣將那個對象再次返回。這樣您就可以繼續使用重定向函數或者返回簡單的字符串了。
這是那個裝飾器的源代碼:
~~~
from functools import wraps
from flask import request
def templated(template=None):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
template_name = template
if template_name is None:
template_name = request.endpoint \
.replace('.', '/') + '.html'
ctx = f(*args, **kwargs)
if ctx is None:
ctx = {}
elif not isinstance(ctx, dict):
return ctx
return render_template(template_name, **ctx)
return decorated_function
return decorator
~~~
### 終端裝飾器
如果您希望使用 werkzeug 路由系統來獲得更多的靈活性。您需要將終點(Endpoint)像 [Rule](http://werkzeug.pocoo.org/docs/routing/#werkzeug.routing.Rule "(在 Werkzeug v0.10)") [http://werkzeug.pocoo.org/docs/routing/#werkzeug.routing.Rule] 中定義的那樣映射起來。通過一個裝飾器是可以做到的,例如:
~~~
from flask import Flask
from werkzeug.routing import Rule
app = Flask(__name__)
app.url_map.add(Rule('/', endpoint='index'))
@app.endpoint('index')
def my_index():
return "Hello world"
~~~
? 版權所有 2013, Armin Ronacher.
- 歡迎使用 Flask
- 前言
- 給有經驗程序員的前言
- 安裝
- 快速入門
- 教程
- 介紹 Flaskr
- 步驟 0: 創建文件夾
- 步驟 1: 數據庫模式
- 步驟 2: 應用設置代碼
- 步驟 3: 創建數據庫
- 步驟 4: 請求數據庫連接
- 步驟 5: 視圖函數
- 步驟 6: 模板
- 步驟 7: 添加樣式
- 福利: 應用測試
- 模板
- 測試 Flask 應用
- 記錄應用錯誤
- 配置處理
- 信號
- 即插視圖
- 應用上下文
- 請求上下文
- 用藍圖實現模塊化的應用
- Flask 擴展
- 與 Shell 共舞
- Flask 代碼模式
- 大型應用
- 應用程序的工廠函數
- 應用調度
- 使用 URL 處理器
- 部署和分發
- 使用 Fabric 部署
- 在 Flask 中使用 SQLite 3
- 在 Flask 中使用 SQLAlchemy
- 上傳文件
- 緩存
- 視圖裝飾器
- 使用 WTForms 進行表單驗證
- 模板繼承
- 消息閃現
- 用 jQuery 實現 Ajax
- 自定義錯誤頁面
- 延遲加載視圖
- 在 Flask 中使用 MongoKit
- 添加 Favicon
- 數據流
- 延遲請求回調
- 添加 HTTP Method Overrides
- 請求內容校驗碼
- 基于 Celery 的后臺任務
- 部署選擇
- mod_wsgi (Apache)
- 獨立 WSGI 容器
- uWSGI
- FastCGI
- CGI
- 聚沙成塔
- API
- JSON 支持
- Flask 中的設計決策
- HTML/XHTML 常見問題
- 安全注意事項
- Flask 中的 Unicode
- Flask 擴展開發
- Pocoo 風格指引
- Python 3 支持
- 升級到最新版本
- Flask Changelog
- 許可證
- 術語表