Flask框架(二):路由與藍圖

畢業男孩發表於2020-08-03

一、路由

使用 route() 裝飾器來把函式繫結到 URL:

@app.route('/')
def index():
    return 'Index Page'

@app.route("/hello")
def view_func():
    return "hello world"

但是能做的不僅僅是這些!你可以動態變化 URL 的某些部分, 還可以為一個函式指定多個規則。

變數規則

通過把 URL 的一部分標記為 <variable_name> 就可以在 URL 中新增變數。標記的 部分會作為關鍵字引數傳遞給函式。通過使用 <converter:variable_name> ,可以 選擇性的加上一個轉換器,為變數指定規則。請看下面的例子:

@app.route('/user/<username>')
def show_user_profile(username):
    # 不宣告轉換器時,預設為String型別,接受任何不包含斜槓的文字
    return 'User %s' % username

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # post_id只能是int型別
    return 'Post %d' % post_id

@app.route('/path/<path:subpath>')
def show_subpath(subpath):
    # path類似string,但可以包含斜槓
    return 'Subpath %s' % subpath

唯一的 URL / 重定向行為

以下兩條規則的不同之處在於是否使用尾部的斜槓。:

@app.route('/projects/')
def projects():
    return 'The project page'

@app.route('/about')
def about():
    return 'The about page'

projects 的 URL 是中規中矩的,尾部有一個斜槓,看起來就如同一個資料夾。 訪問一個沒有斜槓結尾的 URL 時 Flask 會自動進行重定向,幫你在尾部加上一個斜槓。

about 的 URL 沒有尾部斜槓,因此其行為表現與一個檔案類似。如果訪問這個 URL 時新增了尾部斜槓就會得到一個 404 錯誤。這樣可以保持 URL 唯一,並幫助 搜尋

URL 構建

url_for() 函式用於構建指定函式的 URL。它把函式名稱作為第一個 引數。它可以接受任意個關鍵字引數,每個關鍵字引數對應 URL 中的變數。未知變數 將新增到 URL 中作為查詢引數。

為什麼不在把 URL 寫死在模板中,而要使用反轉函式 url_for() 動態構建?

  1. 反轉通常比硬編碼 URL 的描述性更好。

  2. 你可以只在一個地方改變 URL ,而不用到處亂找。

  3. URL 建立會為你處理特殊字元的轉義和 Unicode 資料,比較直觀。

  4. 生產的路徑總是絕對路徑,可以避免相對路徑產生副作用。

  5. 如果你的應用是放在 URL 根路徑之外的地方(如在 /myapplication 中,不在 / 中), url_for() 會為你妥善處理。

例如,這裡我們使用 test_request_context() 方法來嘗試使用 url_for() 。 test_request_context() 告訴 Flask 正在處理一個請求,而實際上也許我們正處在互動 Python shell 之中, 並沒有真正的請求。

from flask import Flask, escape, url_for

app = Flask(__name__)

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

@app.route('/login')
def login():
    return 'login'

@app.route('/user/<username>')
def profile(username):
    return '{}\'s profile'.format(escape(username))

with app.test_request_context():
    print(url_for('index'))
    print(url_for('login'))
    print(url_for('login', next='/'))
    print(url_for('profile', username='John Doe'))

/
/login
/login?next=/
/user/John%20Doe

指定請求方式

在 Flask 中,定義路由其預設的請求方式為:

  • GET
  • OPTIONS(自帶)
  • HEAD(自帶)

利用methods引數可以指定一個介面的請求方式:

@app.route("/hello1", methods=["POST"])
def view_func_1():
    return "hello world 1"

@app.route("/hello2", methods=["GET", "POST"])
def view_func_2():
    return "hello world 2"

 二、藍圖

在一個Flask 應用專案中,如果業務檢視過多,可否將以某種方式劃分出的業務單元單獨維護,將每個單元用到的檢視、靜態檔案、模板檔案等獨立分開?例如從業務角度上,可將整個應用劃分為使用者模組單元、商品模組單元、訂單模組單元,如何分別開發這些不同單元,並最終整合到一個專案應用中?在Django中這種需求是如何實現的?

在Django中我們是將一個個功能劃分為一個個子應用去獨立開發,而在Flask中,使用藍圖Blueprint來分模組組織管理。

 

藍圖實際可以理解為是一個儲存一組檢視方法的容器物件,其具有如下特點:

  • 一個應用可以具有多個Blueprint
  • 可以將一個Blueprint註冊到任何一個未使用的URL下比如 “/user”、“/goods”
  • Blueprint可以單獨具有自己的模板、靜態檔案或者其它的通用操作方法,它並不是必須要實現應用的檢視和函式的
  • 在一個應用初始化時,就應該要註冊需要使用的Blueprint

但是一個Blueprint並不是一個完整的應用,它不能獨立於應用執行,而必須要註冊到某一個應用中。

使用方式

使用藍圖可以分為三個步驟

  1. 建立一個藍圖物件

     user_bp=Blueprint('user',__name__)
  2. 在這個藍圖物件上進行操作,註冊路由,指定靜態資料夾,註冊模版過濾器

     @user_bp.route('/')
     def user_profile():
         return 'user_profile'
  3. 在應用物件上註冊這個藍圖物件

     app.register_blueprint(user_bp)

對於一個打算包含多個檔案的藍圖,通常將建立藍圖物件放到Python包的__init__.py檔案中

--------- project # 工程目錄
  |------ main.py # 啟動檔案
  |------ user  #使用者藍圖
  |  |--- __init__.py  # 此處建立藍圖物件
  |  |--- passport.py  
  |  |--- profile.py
  |  |--- ...
  |
  |------ goods # 商品藍圖
  |  |--- __init__.py
  |  |--- ...
  |...

擴充套件用法

1 指定藍圖的url字首

在應用中註冊藍圖時使用url_prefix引數指定

app.register_blueprint(user_bp, url_prefix='/user')
app.register_blueprint(goods_bp, url_prefix='/goods')

2 藍圖內部靜態檔案

和應用物件不同,藍圖物件建立時不會預設註冊靜態目錄的路由。需要我們在 建立時指定 static_folder 引數。

下面的示例將藍圖所在目錄下的static_admin目錄設定為靜態目錄

admin = Blueprint("admin",__name__,static_folder='static_admin')
app.register_blueprint(admin,url_prefix='/admin')

現在就可以使用/admin/static_admin/<filename>訪問static_admin目錄下的靜態檔案了。

也可通過static_url_path改變訪問路徑

admin = Blueprint("admin",__name__,static_folder='static_admin',static_url_path='/lib')
app.register_blueprint(admin,url_prefix='/admin')

3 藍圖內部模板目錄

藍圖物件預設的模板目錄為系統的模版目錄,可以在建立藍圖物件時使用 template_folder 關鍵字引數設定模板目錄

admin = Blueprint('admin',__name__,template_folder='my_templates')

 

相關文章