在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 可插撥視圖
應(yīng)用環(huán)境
配置管理
大型應(yīng)用
可插撥視圖
Flask 方案
在 Shell 中使用 Flask
針對高級程序員的前言
使用藍(lán)圖的模塊化應(yīng)用
部署方式
信號
排除應(yīng)用錯誤
模板
請求環(huán)境
掌握應(yīng)用錯誤
測試 Flask 應(yīng)用
前言
教程
安裝
快速上手
Flask 擴(kuò)展

可插撥視圖

New in version 0.7.

Flask 0.7 版本引入了可插撥視圖。可插撥視圖基于使用類來代替函數(shù),其靈感來自于 Django 的通用視圖??刹鍝芤晥D的主要用途是用可定制的、可插撥的視圖來替代部分實現(xiàn)。

基本原理

假設(shè)有一個函數(shù)用于從數(shù)據(jù)庫中載入一個對象列表并在模板中渲染:

@app.route('/users/')
def show_users(page):
    users = User.query.all()
    return render_template('users.html', users=users)

上例簡單而靈活。但是如果要把這個視圖變成一個可以用于其他模型和模板的通用視圖, 那么這個視圖還是不夠靈活。因此,我們就需要引入可插撥的、基于類的視圖。第一步, 可以把它轉(zhuǎn)換為一個基礎(chǔ)視圖:

from flask.views import View

class ShowUsers(View):

    def dispatch_request(self):
        users = User.query.all()
        return render_template('users.html', objects=users)

app.add_url_rule('/users/', view_func=ShowUsers.as_view('show_users'))

就如你所看到的,必須做的是創(chuàng)建一個 flask.views.View 的子類,并且執(zhí)行 dispatch_request() 。然后必須通過使用 as_view() 方法把類轉(zhuǎn)換為實際視圖函數(shù)。傳遞給函數(shù)的 字符串是最終視圖的名稱。但是這本身沒有什么幫助,所以讓我們來小小地重構(gòu)一下:

from flask.views import View

class ListView(View):

    def get_template_name(self):
        raise NotImplementedError()

    def render_template(self, context):
        return render_template(self.get_template_name(), **context)

    def dispatch_request(self):
        context = {'objects': self.get_objects()}
        return self.render_template(context)

class UserView(ListView):

    def get_template_name(self):
        return 'users.html'

    def get_objects(self):
        return User.query.all()

這樣做對于示例中的小應(yīng)用沒有什么用途,但是可以足夠清楚的解釋基本原理。當(dāng)你有一個基礎(chǔ)視圖類時,問題就來了:類的 self 指向什么?解決之道是:每當(dāng)請求發(fā)出時就創(chuàng)建一個類的新實例,并且根據(jù)來自 URL 規(guī)則的參數(shù)調(diào)用 dispatch_request() 方法。類本身根據(jù)參數(shù)實例化后傳遞給 as_view() 函數(shù)。例如可以這樣寫一個類:

class RenderTemplateView(View):
    def __init__(self, template_name):
        self.template_name = template_name
    def dispatch_request(self):
        return render_template(self.template_name)

然后可以這樣注冊:

app.add_url_rule('/about', view_func=RenderTemplateView.as_view(
    'about_page', template_name='about.html'))

方法提示

可插撥視圖可以像普通函數(shù)一樣加入應(yīng)用。加入的方式有兩種,一種是使用 route() ,另一種是使用更好的 add_url_rule() 。在加入的視圖中應(yīng)該提供所使用的 HTTP 方法的名稱。提供名稱的方法是使用 methods 屬性:

class MyView(View):
    methods = ['GET', 'POST']

    def dispatch_request(self):
        if request.method == 'POST':
            ...
        ...

app.add_url_rule('/myview', view_func=MyView.as_view('myview'))

基于方法調(diào)度

對于 REST 式的 API 來說,為每種 HTTP 方法提供相對應(yīng)的不同函數(shù)顯得尤為有用。使用 flask.views.MethodView 可以輕易做到這點。在這個類中,每個 HTTP 方法 都映射到一個同名函數(shù)(函數(shù)名稱為小寫字母):

from flask.views import MethodView

class UserAPI(MethodView):

    def get(self):
        users = User.query.all()
        ...

    def post(self):
        user = User.from_form_data(request.form)
        ...

app.add_url_rule('/users/', view_func=UserAPI.as_view('users'))

使用這種方式,不必提供 methods 屬性,它會自動使用相應(yīng)的類方法。

裝飾視圖

視圖函數(shù)會被添加到路由系統(tǒng)中,而視圖類則不會。因此視圖類不需要裝飾,只能以手工 使用 as_view() 來裝飾返回值:

def user_required(f):
    """Checks whether user is logged in or raises error 401."""
    def decorator(*args, **kwargs):
        if not g.user:
            abort(401)
        return f(*args, **kwargs)
    return decorator

view = user_required(UserAPI.as_view('users'))
app.add_url_rule('/users/', view_func=view)

自 Flask 0.8 版本開始,新加了一種選擇:在視圖類中定義裝飾的列表:

class UserAPI(MethodView):
    decorators = [user_required]

請牢記:因為從調(diào)用者的角度來看,類的 self 被隱藏了,所以不能在類的方法上單獨(dú)使用裝飾器。

用于 API 的方法視圖

網(wǎng)絡(luò) API 經(jīng)常直接對應(yīng) HTTP 變量,因此很有必要實現(xiàn)基于 MethodView 的 API 。即多數(shù)時候, API 需要把不同的 URL 規(guī)則應(yīng)用到同一個方法視圖。例如,假設(shè)你需要這樣使用一個 user 對象:

URL 方法 說明
/users/ GET 給出一個包含所有用戶的列表
/users/ POST 創(chuàng)建一個新用戶
/users/ GET 顯示一個用戶
/users/ PUT 更新一個用戶
/users/ DELETE 刪除一個用戶

那么如何使用 MethodView 來實現(xiàn)呢?方法是使用多個規(guī)則對應(yīng) 到同一個視圖。

假設(shè)視圖是這樣的:

class UserAPI(MethodView):

    def get(self, user_id):
        if user_id is None:
            # 返回一個包含所有用戶的列表
            pass
        else:
            # 顯示一個用戶
            pass

    def post(self):
        # 創(chuàng)建一個新用戶
        pass

    def delete(self, user_id):
        # 刪除一個用戶
        pass

    def put(self, user_id):
        # update a single user
        pass

那么如何把這個視圖掛接到路由系統(tǒng)呢?方法是增加兩個規(guī)則并為每個規(guī)則顯式聲明方法:

user_view = UserAPI.as_view('user_api')
app.add_url_rule('/users/', defaults={'user_id': None},
                 view_func=user_view, methods=['GET',])
app.add_url_rule('/users/', view_func=user_view, methods=['POST',])
app.add_url_rule('/users/<int:user_id>', view_func=user_view,
                 methods=['GET', 'PUT', 'DELETE'])

如果你有許多類似的 API ,那么可以代碼如下:

def register_api(view, endpoint, url, pk='id', pk_type='int'):
    view_func = view.as_view(endpoint)
    app.add_url_rule(url, defaults={pk: None},
                     view_func=view_func, methods=['GET',])
    app.add_url_rule(url, view_func=view_func, methods=['POST',])
    app.add_url_rule('%s<%s:%s>' % (url, pk_type, pk), view_func=view_func,
                     methods=['GET', 'PUT', 'DELETE'])

register_api(UserAPI, 'user_api', '/users/', pk='user_id')

? Copyright 2013, Armin Ronacher. Created using Sphinx.

上一篇:掌握應(yīng)用錯誤下一篇:教程