第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Flask 標準類視圖

在前面的小節(jié)講解 Flask 路由時,采用的方式是:將 URL 路徑和一個函數(shù)關(guān)聯(lián),當 Flask 框架接收到請求后,會根據(jù)請求的 URL 調(diào)用相應(yīng)的函數(shù)進行處理。

本小節(jié)講解設(shè)置路由的新方法:將 URL 路徑和一個視圖類關(guān)聯(lián),當 Flask 框架接收到請求后,會根據(jù)請求的 URL 調(diào)用相應(yīng)的視圖類進行處理。

1. 視圖函數(shù)與視圖類

在前面小節(jié)中,將 URL 路徑和一個函數(shù)關(guān)聯(lián),這個函數(shù)又被稱為視圖函數(shù),F(xiàn)lask 框架會根據(jù)請求的 URL 調(diào)用相應(yīng)的視圖函數(shù)進行處理,例如:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'hello world'

app.run(debug = True)

在這個例子中,URL 是 /,對應(yīng)的處理函數(shù)是 index,當訪問路徑為 / 時,會執(zhí)行函數(shù) index。

在前面的小節(jié)中,使用函數(shù)處理相關(guān)的 URL,所以一般簡稱為視圖函數(shù)。在 Flask 中,也可以使用類來處理相關(guān)的 URL,這樣的也被稱為視圖類。

2. 基本用法

2.1 基本用法

Flask.views.View 是 Flask 的標準視圖類,用戶定義的視圖類需要繼承于 Flask.views.View。使用視圖類的步驟如下:

  1. 用戶定義一個視圖類,繼承于 flask.views.View;
  2. 在視圖類中定義方法 dispatch_request,處理請求、返回 HTML 文本給客戶端;
  3. 使用 app.add_url_rule (rule, view_func) 將 URL 路徑和視圖類綁定

下面是視圖類的例子 basis.py

from flask import Flask, views
app = Flask(__name__)

class Index(views.View) :
    def dispatch_request(self):
        return 'hello world'

app.add_url_rule(rule='/', view_func = Index.as_view('Index'))
app.run(debug = True)

在第 4 行,定義視圖類 Index 用于處理路徑為 / 的 URL,視圖類 Index 繼承于 Flask.views.View;在第 5 行,定義方法 dispatch_request,該方法返回 ‘hello world’ 給客戶端;在第 8 行,將路徑為 / 的 URL 和視圖類 Index 綁定。

Tips:Index.as_view (‘Index’) 創(chuàng)建一個名稱為 Index 的視圖函數(shù),app.add_url_rule 實際上是將 URL 路徑和視圖函數(shù)(由視圖類的 as_view 轉(zhuǎn)換而來)綁定。

2.2 as_view 函數(shù)的功能

視圖類的本質(zhì)是視圖函數(shù),函數(shù) View.as_view () 返回一個視圖函數(shù),為了透徹理解 as_view 函數(shù)的功能,我們自己實現(xiàn)一個簡化版本的 as_view 函數(shù),創(chuàng)建文件 as-view.py 如下:

from flask import Flask
app = Flask(__name__)

class Index:
    def dispatch_request(self):
        return 'hello world'

    @staticmethod
    def as_view(name):
        index = Index()
        return index.dispatch_request

app.add_url_rule(rule='/', view_func = Index.as_view('Index'))
app.run(debug = True)

這個小節(jié)的程序功能與上一個小節(jié)的程序功能完全相同,不同之處:在本小節(jié)的程序中,我們實現(xiàn)了一個簡化版本的 as_view 函數(shù)。

在第 8 行,定義了一個靜態(tài)方法 as_view,它首先創(chuàng)建一個實例 index,然后返回實例 index 的 dispatch_request 方法。即 view_func 指向了實例 index 的方法 dispatch_request,當訪問頁面路徑 / 時,最終會調(diào)用 index.dispatch_request ()。

3. 繼承

使用類視圖的好處是支持繼承,可以把一些共性的東西放在父類中,其他子類可以繼承。下面通過一個例子 inherit.py 說明如何使用繼承。

3.1 父類 BaseView

首先,定義視圖類 BaseView,它繼承于 flask.views.View,它是用戶自定義的視圖類的父類,代碼如下:

from flask import Flask, render_template, views
app = Flask(__name__)

class BaseView(views.View):
    def get_template(self):
        raise NotImplementedError()

    def get_data(self):        
        raise NotImplementedError()

    def dispatch_request(self):
        data = self.get_data()
        template = self.get_template()
        return render_template(template, **data)

BaseView 與子類之間的關(guān)系如下:BaseView 提供了 dispatch_request 方法的實現(xiàn),子類繼承了這個方法,不需要重新實現(xiàn) dispatch_request;BaseView 定義了兩個接口函數(shù) get_template 和 get_data,子類必須實現(xiàn)這兩個方法。

在 BaseView 中,get_template 和 get_data 的缺省實現(xiàn)是拋出錯誤 NotImplementedError,如果子類忘記定義了這兩個方法,在運行時會報錯。

在 BaseView 中,定義了方法 displach_request (),調(diào)用 get_template () 獲得模板的路徑,調(diào)用 get_data () 獲取模板的參數(shù),最后調(diào)用 render_template 根據(jù)模板路徑 template 和模板參數(shù) data 渲染輸出。

3.2 子類 UserView

實現(xiàn)子類 UserView,它繼承于 BaseView,代碼如下:

class UserView(BaseView):
    def get_template(self):
        return 'user.html'

    def get_data(self):
        return {
            'name': 'zhangsan',
            'gender': 'male',
        }

在子類 UserView 中,get_template 返回模板路徑為 ‘user.html’,get_data 返回模板參數(shù) name 和 gender。BaseView 中已經(jīng)實現(xiàn)了視圖類的 dispatch_request 方法,子類 UserView 繼承了 BaseView 的 dispatch_request 方法,因此不需要再重新實現(xiàn)該方法。

3.3 綁定 URL

使用 app.add_url_rule 綁定 URL 和視圖類,如下:

app.add_url_rule('/user/', view_func=UserView.as_view('UserView'))
app.run(debug = True)

將路徑為 /user/ 的 URL 和視圖類 UserView 綁定,當訪問路徑為 /user/ 的 URL 時,最終由 BaseView.dispatch_request 進行處理。

3.4 模板 user.html

創(chuàng)建模板 user.html:

<html>
<body>
  <h2>name = {{ name }}</h2>
  <h2>gender = {{ gender }}</h2>
</body>
</html>

3.5 運行結(jié)果

在瀏覽器中訪問 http://localhost:5000/user,顯示如下:

圖片描述

4. 使用裝飾器

本小節(jié)通過具體的例子講解如何在視圖函數(shù)和視圖類中使用裝飾器。

4.1 檢查登錄的功能

在 Web 應(yīng)用中,相當一部分功能需要用戶登錄才能使用,比如說:訪問用戶的個人信息頁面,在訪問頁面之前,需要檢查用戶是否已經(jīng)成功登錄,只有成功登錄后才執(zhí)行后續(xù)的功能邏輯。我們可以這樣實現(xiàn):

def check_login():
    if 用戶已經(jīng)登錄:
        return True
    else:        
        return False

@app.route('/page1', page1)
def page1():
    if not check_login():
        return '請先登錄'
    執(zhí)行 page1 的功能

@app.route('/page2', page2)
def page2():
    if not check_login():
        return '請先登錄'
    執(zhí)行 page2 的功能

在上面例子中,處理 /page1 和 /page2 時需要檢查登錄,在函數(shù) page1 () 和 page2 () 的頭部調(diào)用 check_login 函數(shù)。這種方法雖然實現(xiàn)了功能,但不夠簡潔。

4.2 檢查登錄的裝飾器

使用裝飾器實現(xiàn)登錄的功能,定義檢查登錄的裝飾器 check_login:

from functools import wraps

def check_login(original_function):
    @wraps(original_function)
    def decorated_function(*args,**kwargs):
        user = request.args.get("user")
        if user and user == 'zhangsan':
             return original_function(*args, **kwargs)
        else:
            return '請先登錄'
    return decorated_function

裝飾器 check_login 本質(zhì)是一個函數(shù),它的輸入是一個函數(shù) original_function,它的輸出也是一個函數(shù) decorated_function。original_function 是原先的處理 URL 的視圖函數(shù),它不包含檢查登錄的功能邏輯;decorated_function 是在 original_function 的基礎(chǔ)上進行功能擴充的函數(shù),它首先檢查是否已經(jīng)登錄,如果已經(jīng)登錄則調(diào)用 original_function,如果沒有登錄則返回錯誤。

在第 6 行和第 7 行,檢查請求中的參數(shù) user 是否為 ‘zhangsan’,如果 user 等于 ‘zhangsan’,表示用戶已經(jīng)登錄,則調(diào)用 original_function,否則返回 ‘請先登錄’。

在第 4 行,使用 functools.wraps (original_function) 保留原始函數(shù) original_function 的屬性。

4.3 在視圖函數(shù)中使用裝飾器

本小節(jié)講解在視圖函數(shù)中使用裝飾器,創(chuàng)建文件 decorator/view-func.py:

from flask import Flask, request
from functools import wraps
app = Flask(__name__)

def check_login(original_function):
    # 請參考 4.2 小節(jié)

@app.route('/page1')
@check_login
def page1():
    return 'page1'

@app.route('/page2')
@check_login
def page2():
    return 'page2'

app.run(debug = True)

程序有 2 個頁面 /page1 和 /page2,只有登錄的用戶才能訪問這兩個頁面。

函數(shù) page1 被裝飾了 2 次,它的原始功能是處理 /page1 的頁面邏輯,被 @check_login 裝飾后,具備了檢查登錄的功能,被 @app.route (’/page1’) 裝飾后,綁定到路徑為 /page1 的 URL,當訪問 /page1 時,會訪問 page1 函數(shù)。函數(shù) page2 的功能類似。

與 4.1 小節(jié)相比,使用裝飾器后,檢查登錄的功能與 page1 和 page2 本身的功能是分離的。

4.4 在視圖類中使用裝飾器

本小節(jié)講解在視圖類中使用裝飾器,創(chuàng)建文件 decorator/view-class.py:

from flask import Flask, request, views
from functools import wraps
app = Flask(__name__)

def check_login(func):
    # 請參考 4.2 小節(jié)

class Page1(views.View):
    decorators = [check_login]

    def dispatch_request(self):
        return 'Page1'

class Page2(views.View):
    decorators = [check_login]

    def dispatch_request(self):
        return 'Page2'

app.add_url_rule(rule='/page1', view_func = Page1.as_view('Page1'))
app.add_url_rule(rule='/page2', view_func = Page2.as_view('Page2'))
app.run(debug = True)

程序有 2 個頁面 /page1 和 /page2,只有登錄的用戶才能訪問這兩個頁面。

類 Page1 的原始功能是處理 /page1 的頁面邏輯,在第 9 行,decorators = [check_login] 設(shè)定視圖類的裝飾器,當訪問 /page1 時,首先執(zhí)行檢查登錄,然后再執(zhí)行原始的功能。

與 4.1 小節(jié)相比,使用裝飾器后,檢查登錄的功能與 page1 和 page2 本身的功能是分離的。

4.5 運行效果

在瀏覽器中輸入:http://localhost:5000/page1?user=zhangsan, URL 中的查詢參數(shù) user=zhangsan 表示已經(jīng)登錄,顯示如下:

圖片描述

5. 源代碼下載

6. 小結(jié)

本小節(jié)講解設(shè)置路由的新方法:將 URL 路徑和一個視圖類關(guān)聯(lián),當 Flask 框架接收到請求后,會根據(jù)請求的 URL 調(diào)用相應(yīng)的視圖類進行處理。對本節(jié)的重點,使用思維導圖概括如下:

圖片描述