如何用Flask中的Blueprints構建大型Web應用

来源:https://www.cnblogs.com/huaweiyun/p/18098247
-Advertisement-
Play Games

本文分享自華為雲社區《構建大型Web應用Flask中的Blueprints指南》,作者: 檸檬味擁抱。 什麼是Blueprints? Blueprints是Flask中的一種模式,用於將應用程式分解為可重用的模塊。每個藍圖實際上是一個包含一組路由、視圖和靜態文件的Python模塊。通過使用藍圖,我們 ...


本文分享自華為雲社區《構建大型Web應用Flask中的Blueprints指南》,作者: 檸檬味擁抱。

什麼是Blueprints?

Blueprints是Flask中的一種模式,用於將應用程式分解為可重用的模塊。每個藍圖實際上是一個包含一組路由、視圖和靜態文件的Python模塊。通過使用藍圖,我們可以將相關功能的代碼組織在一起,從而更容易地管理和維護我們的應用程式。
image.png

為什麼要使用Blueprints?

  1. 模塊化組織:將相關功能的代碼放在一起,使得代碼更易於理解和維護。
  2. 路由命名空間:通過在藍圖中定義路由,可以避免路由衝突,並更好地組織應用程式的URL結構。
  3. 可重用性:藍圖可以在多個應用程式中重覆使用,從而促進了代碼的可重用性和可擴展性。

如何使用Blueprints?

首先,讓我們創建一個簡單的Flask應用,並使用藍圖來組織路由和視圖。

# app.py
from flask import Flask
from auth import auth_bp
from blog import blog_bp

app = Flask(__name__)

# 註冊藍圖
app.register_blueprint(auth_bp)
app.register_blueprint(blog_bp)

if __name__ == "__main__":
    app.run(debug=True)

現在,讓我們定義兩個藍圖:一個用於身份驗證,另一個用於博客功能。

# auth.py
from flask import Blueprint

auth_bp = Blueprint('auth', __name__)

@auth_bp.route('/login')
def login():
    return 'Login Page'

@auth_bp.route('/logout')
def logout():
    return 'Logout Page'
# blog.py
from flask import Blueprint

blog_bp = Blueprint('blog', __name__)

@blog_bp.route('/')
def index():
    return 'Blog Home Page'

@blog_bp.route('/post/<int:post_id>')
def post(post_id):
    return f'Viewing post {post_id}'

在上面的代碼中,我們定義了兩個藍圖:auth_bp用於身份驗證相關的路由,blog_bp用於博客相關的路由。

代碼解析

  • 我們首先導入了Blueprint類以及Flask類。
  • 然後我們創建了Flask應用程式實例。
  • 接著,我們將定義好的藍圖註冊到應用程式中,每個藍圖都有一個唯一的名稱和一組路由。
  • 最後,我們運行應用程式。

在每個藍圖中,我們使用@blueprint.route()裝飾器定義了不同的路由。在實際應用中,我們可以將相關功能的路由和視圖添加到相應的藍圖中,以實現模塊化的組織。

高級用法:藍圖之間的通信

除了簡單的路由註冊外,Blueprints還可以通過一些高級技巧實現更複雜的功能,例如藍圖之間的通信。讓我們通過一個示例來說明這一點。

假設我們的博客應用需要在登錄後顯示用戶的個人資料。我們可以在auth藍圖中處理登錄邏輯,併在blog藍圖中顯示用戶的個人資料。為了實現這一點,我們可以在藍圖之間共用數據。

# auth.py
from flask import Blueprint, session

auth_bp = Blueprint('auth', __name__)

@auth_bp.route('/login')
def login():
    # 模擬登錄,將用戶信息存儲在session中
    session['user'] = {'username': 'example_user'}
    return 'Login Successful'

@auth_bp.route('/logout')
def logout():
    # 模擬登出,清除session中的用戶信息
    session.pop('user', None)
    return 'Logout Successful'
# blog.py
from flask import Blueprint, session

blog_bp = Blueprint('blog', __name__)

@blog_bp.route('/')
def index():
    if 'user' in session:
        username = session['user']['username']
        return f'Welcome, {username}! This is your Blog Home Page'
    else:
        return 'Welcome to the Blog Home Page'

@blog_bp.route('/profile')
def profile():
    if 'user' in session:
        username = session['user']['username']
        return f'Hello, {username}! This is your Profile Page'
    else:
        return 'Please login to view your Profile'

在上面的示例中,我們使用了Flask的session對象來在藍圖之間共用用戶信息。在auth藍圖中,用戶成功登錄後,我們將用戶信息存儲在session中;而在blog藍圖中,我們可以訪問session中的用戶信息來顯示用戶的個人資料。

高級用法解析

  • 我們使用了Flask的session對象來在不同請求之間存儲用戶信息。session是一個類似字典的對象,可以用來存儲和訪問用戶的會話數據。
  • auth藍圖中,我們在用戶登錄成功後將用戶信息存儲在session中;而在blog藍圖中,我們通過訪問session中的用戶信息來顯示用戶的個人資料。
  • 這種方式使得不同的藍圖可以共用數據,實現了更靈活和可擴展的應用程式結構。

藍圖的模板和靜態文件

除了路由和視圖之外,Blueprints還可以用於組織模板和靜態文件,使得應用程式的文件結構更加清晰。讓我們通過一個例子來說明如何在藍圖中使用模板和靜態文件。

首先,我們創建一個包含模板和靜態文件的藍圖。

# blog.py
from flask import Blueprint, render_template

blog_bp = Blueprint('blog', __name__, template_folder='templates', static_folder='static')

@blog_bp.route('/')
def index():
    return render_template('index.html')

@blog_bp.route('/about')
def about():
    return render_template('about.html')

在上面的示例中,我們在創建blog_bp藍圖時指定了模板文件夾和靜態文件夾的路徑。這樣,Flask就知道在哪裡查找模板和靜態文件。

接下來,我們在相應的模板文件夾中創建模板文件。

<!-- templates/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Blog Home</title>
    <link rel="stylesheet" href="{{ url_for('blog.static', filename='style.css') }}">
</head>
<body>
    <h1>Welcome to the Blog</h1>
    <p>This is the home page of our blog.</p>
</body>
</html>
<!-- templates/about.html -->
<!DOCTYPE html>
<html>
<head>
    <title>About</title>
    <link rel="stylesheet" href="{{ url_for('blog.static', filename='style.css') }}">
</head>
<body>
    <h1>About Us</h1>
    <p>Learn more about our blog and team.</p>
</body>
</html>

在模板文件中,我們使用url_for()函數來生成靜態文件的URL,並指定了blog.static作為藍圖的靜態文件路徑。

最後,我們在靜態文件夾中添加樣式表文件。

/* static/style.css */
body {
    font-family: Arial, sans-serif;
    background-color: #f0f0f0;
    margin: 0;
    padding: 0;
}
h1 {
    color: #333;
}
p {
    color: #666;
}

解析

  • 我們使用了template_folderstatic_folder參數來指定藍圖的模板文件夾和靜態文件夾的路徑。
  • 在模板文件中,我們使用url_for()函數生成靜態文件的URL,並指定了藍圖的靜態文件路徑。這樣做可以確保在藍圖之間的移動時靜態文件路徑仍然有效。
  • 靜態文件的引用方式與普通的Flask應用程式中相同,但需要明確指定藍圖的靜態文件路徑。

通過這種方式,我們可以將模板和靜態文件與特定的藍圖相關聯,使得文件結構更加清晰,並使應用程式更易於維護和擴展。

測試和文檔

在構建大型Web應用程式時,測試和文檔是不可或缺的組成部分。Blueprints可以與測試框架和文檔生成工具集成,以便更好地管理和維護我們的應用程式。

測試

在使用Blueprints時,我們可以針對每個藍圖編寫單元測試,以確保其功能正常。通常,測試藍圖的方法與測試普通的Flask應用程式相同,只需導入相應的藍圖並模擬請求即可。

# test_blog.py
import unittest
from app import app

class TestBlogBlueprint(unittest.TestCase):

    def setUp(self):
        self.app = app.test_client()

    def test_index(self):
        response = self.app.get('/blog/')
        self.assertEqual(response.status_code, 200)
        self.assertIn(b'Welcome to the Blog', response.data)

    def test_about(self):
        response = self.app.get('/blog/about')
        self.assertEqual(response.status_code, 200)
        self.assertIn(b'About Us', response.data)

if __name__ == '__main__':
    unittest.main()

在上面的示例中,我們編寫了針對blog藍圖的單元測試,以確保其indexabout路由能夠正常工作。

文檔

在使用Blueprints時,我們還可以通過文檔生成工具自動生成API文檔,以便開發人員和團隊成員更好地理解應用程式的結構和功能。

# 使用Flask-APIDoc生成API文檔
from flask_apidoc import ApiDoc

apidoc = ApiDoc()

# 將藍圖註冊到apidoc
apidoc.register_blueprint(auth_bp)
apidoc.register_blueprint(blog_bp)

if __name__ == '__main__':
    apidoc.run(debug=True)

通過將藍圖註冊到文檔生成工具中,我們可以自動生成包含所有藍圖路由和視圖的API文檔。這樣,開發人員就可以更輕鬆地查看和理解應用程式的結構和功能。

部署和擴展

一旦我們構建了具有模塊化結構的大型Web應用程式,就需要考慮如何部署和擴展該應用程式,以確保其性能和可用性。讓我們討論一下在部署和擴展過程中如何處理Blueprints。

部署

在部署Flask應用程式時,可以使用各種Web伺服器和部署工具,例如Gunicorn、uWSGI和Docker。部署過程中,只需確保將應用程式實例化的代碼和藍圖註冊的代碼包含在主應用程式文件中即可。

# app.py
from flask import Flask
from auth import auth_bp
from blog import blog_bp

app = Flask(__name__)

# 註冊藍圖
app.register_blueprint(auth_bp)
app.register_blueprint(blog_bp)

if __name__ == "__main__":
    app.run(debug=True)

將所有藍圖註冊到主應用程式文件中可以確保在部署時所有路由和視圖都能正確載入。

擴展

當我們的應用程式需要擴展時,例如增加新的功能模塊或處理更多的用戶請求,Blueprints可以幫助我們輕鬆地擴展應用程式。我們只需創建新的藍圖,並將其註冊到主應用程式中即可。

# admin.py
from flask import Blueprint

admin_bp = Blueprint('admin', __name__)

@admin_bp.route('/dashboard')
def dashboard():
    return 'Admin Dashboard'
# app.py
from flask import Flask
from auth import auth_bp
from blog import blog_bp
from admin import admin_bp

app = Flask(__name__)

# 註冊藍圖
app.register_blueprint(auth_bp)
app.register_blueprint(blog_bp)
app.register_blueprint(admin_bp, url_prefix='/admin')

if __name__ == "__main__":
    app.run(debug=True)

在上面的示例中,我們創建了一個名為admin_bp的新藍圖,並將其註冊到主應用程式中。通過使用url_prefix參數,我們可以指定藍圖的URL首碼,從而輕鬆地組織不同模塊的路由。

性能優化

在構建大型Web應用程式時,性能是一個關鍵問題。Blueprints可以幫助我們實現更好的性能優化,通過合理的路由分發和模塊化設計來提高應用程式的響應速度和可伸縮性。

藍圖的惰性載入

Flask中的Blueprints是惰性載入的,這意味著只有在應用程式第一次收到請求時才會註冊和初始化藍圖。這種機制確保了應用程式在啟動時載入的速度較快,因為只有在需要時才會載入相關的功能模塊。

路由分發

通過合理地組織和分發路由,可以進一步提高應用程式的性能。例如,可以將具有相似功能的路由放在同一個藍圖中,以減少路由匹配的開銷。

# blog.py
from flask import Blueprint

blog_bp = Blueprint('blog', __name__)

@blog_bp.route('/')
def index():
    return 'Blog Home Page'

@blog_bp.route('/post/<int:post_id>')
def post(post_id):
    return f'Viewing post {post_id}'

在上面的示例中,所有與博客相關的路由都放在了一個名為blog_bp的藍圖中,這樣可以提高路由匹配的效率。

靜態文件和緩存

對於靜態文件,可以使用Nginx、CDN或Flask的靜態文件緩存等方式來加速靜態文件的訪問。另外,對於動態內容,可以使用緩存技術來減少資料庫查詢和計算的次數,從而提高響應速度。

安全性考慮

在構建大型Web應用程式時,安全性是至關重要的。Blueprints可以幫助我們實現一些安全性措施,以保護應用程式免受常見的安全威脅。

藍圖級別的中間件

Flask允許我們在藍圖級別應用中間件,這樣我們就可以針對特定的藍圖應用安全性措施。

# auth.py
from flask import Blueprint, request, abort

auth_bp = Blueprint('auth', __name__)

@auth_bp.before_request
def check_request():
    if not request.is_secure:
        abort(403)

在上面的示例中,我們在auth藍圖中應用了一個中間件,用於檢查請求是否是安全的(即使用HTTPS)。如果請求不是安全的,就會返回403禁止訪問的響應。

藍圖的許可權控制

通過在藍圖中實現許可權控制邏輯,我們可以限制用戶對特定功能的訪問。

# admin.py
from flask import Blueprint, abort

admin_bp = Blueprint('admin', __name__)

@admin_bp.route('/dashboard')
def dashboard():
    if not current_user.is_admin:
        abort(403)
    return 'Admin Dashboard'

在上面的示例中,我們在admin藍圖中的dashboard路由中實現了許可權控制邏輯,只有管理員用戶才能訪問該頁面。

安全頭部設置

Flask提供了一些內置的安全頭部設置,可以在應用程式中設置以增強安全性,例如X-Content-Type-OptionsX-Frame-OptionsContent-Security-Policy等。

# app.py
from flask import Flask
from flask_talisman import Talisman

app = Flask(__name__)
talisman = Talisman(app)

在上面的示例中,我們使用Flask-Talisman擴展來設置一些安全頭部,以保護應用程式免受XSS和點擊劫持等攻擊。

總結

總的來說,本文深入探討了在Flask中使用Blueprints來構建大型Web應用程式的方法。Blueprints提供了一種模塊化的方式來組織應用程式的路由、視圖、模板和靜態文件,使得應用程式更易於管理和維護。通過合理利用Blueprints,我們可以實現以下幾個方面的優勢:

  1. 模塊化組織: 將相關功能的代碼放在一起,使得代碼更易於理解和維護。
  2. 路由命名空間: 避免路由衝突,並更好地組織應用程式的URL結構。
  3. 可重用性: 藍圖可以在多個應用程式中重覆使用,促進了代碼的可重用性和可擴展性。
  4. 高級功能支持: 可以實現藍圖之間的通信、模板和靜態文件的組織、測試和文檔的生成、部署和擴展以及性能優化和安全性考慮等功能。

通過本文所介紹的內容,開發人員可以更好地利用Blueprints來構建大型、模塊化的Web應用程式,併在實踐中不斷優化和完善應用程式的結構和功能,以滿足不斷變化的需求和挑戰。

 

點擊關註,第一時間瞭解華為雲新鮮技術~

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 數據來源分析 網站鏈接: aHR0cHM6Ly9tdXNpYy4xNjMuY29tLyMvZGlzY292ZXIvdG9wbGlzdD9pZD0zNzc4Njc4 音樂數據包分析 正常流程抓包分析數據, 找到音頻鏈接 找到歌曲信息對應數據包 分析加密參數位置 找到對應的加密位置, 其餘就去扣 ...
  • 一、 智能文檔處理介紹 智能文檔處理(Intelligent Document Processing, IDP)是利用人工智慧(AI)、機器學習(ML)、電腦視覺(CV)、自然語言處理(NLP)等技術自動化地捕獲、理解、處理和分析文檔內容的過程。不同於傳統的文檔管理系統,IDP能夠處理結構化、半結 ...
  • 前置工作 導包(mysql-connector-java、mybatis) 實體類 Mapper層 1.介面 public interface BookMapper { public Book getBookById(Integer bookID); } 2.創建Mapper的映射文件 <?xml ...
  • 本文是 SpringBoot 開發的乾貨集中營,涵蓋了日常開發中遇到的諸多問題,通篇著重講解如何快速解決問題,部分重點問題會講解原理,以及為什麼要這樣做。便於大家快速處理實踐中經常遇到的小問題,既方便自己也方便他人,老鳥和新手皆適合,值得收藏 1. 哪裡可以搜索依賴包的 Maven 坐標和版本 ...
  • Redis通過結合純記憶體操作、單線程模型、IO多路復用技術和一系列精心設計的高效數據結構,實現了在高併發、低延遲場景下的優秀性能表現。 ...
  • 拓展閱讀 blog-engine-01-常見博客引擎 jekyll/hugo/Hexo/Pelican/Gatsby/VuePress/Nuxt.js/Middleman 對比 blog-engine-02-通過博客引擎 jekyll 構建 github pages 博客實戰筆記 blog-engi ...
  • 核心註解 1. @SpringBootApplication 主要用於開啟自動配置,它也是一個組合註解,主要組合了 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 2. @EnableAutoConfiguration ...
  • 距離2020年已經過去很久了,各大編譯器對於C++20各項標準的支持也日趨完善,無棧協程也是其中之一,所以我就嘗試著拿協程與`io_uring`實現了一下proactor模式,這篇文章用來記錄一下我的設計和想法。除此之外,我們能在網路上找到許多優秀的C++20協程的教程以及許多優秀的協程應用(庫),... ...
一周排行
    -Advertisement-
    Play Games
  • 最近做項目過程中,使用到了海康相機,官方只提供了C/C++的SDK,沒有搜尋到一個合適的封裝了的C#庫,故自己動手,簡單的封裝了一下,方便大家也方便自己使用和二次開發 ...
  • 前言 MediatR 是 .NET 下的一個實現消息傳遞的庫,輕量級、簡潔高效,用於實現進程內的消息傳遞機制。它基於中介者設計模式,支持請求/響應、命令、查詢、通知和事件等多種消息傳遞模式。通過泛型支持,MediatR 可以智能地調度不同類型的消息,非常適合用於領域事件處理。 在本文中,將通過一個簡 ...
  • 前言 今天給大家推薦一個超實用的開源項目《.NET 7 + Vue 許可權管理系統 小白快速上手》,DncZeus的願景就是做一個.NET 領域小白也能上手的簡易、通用的後臺許可權管理模板系統基礎框架。 不管你是技術小白還是技術大佬或者是不懂前端Vue 的新手,這個項目可以快速上手讓我們從0到1,搭建自 ...
  • 第1章:WPF概述 本章目標 瞭解Windows圖形演化 瞭解WPF高級API 瞭解解析度無關性概念 瞭解WPF體繫結構 瞭解WPF 4.5 WPF概述 ​ 歡迎使用 Windows Presentation Foundation (WPF) 桌面指南,這是一個與解析度無關的 UI 框架,使用基於矢 ...
  • 在日常開發中,並不是所有的功能都是用戶可見的,還在一些背後默默支持的程式,這些程式通常以服務的形式出現,統稱為輔助角色服務。今天以一個簡單的小例子,簡述基於.NET開發輔助角色服務的相關內容,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 第3章:佈局 本章目標 理解佈局的原則 理解佈局的過程 理解佈局的容器 掌握各類佈局容器的運用 理解 WPF 中的佈局 WPF 佈局原則 ​ WPF 視窗只能包含單個元素。為在WPF 視窗中放置多個元素並創建更貼近實用的用戶男面,需要在視窗上放置一個容器,然後在這個容器中添加其他元素。造成這一限制的 ...
  • 前言 在平時項目開發中,定時任務調度是一項重要的功能,廣泛應用於後臺作業、計劃任務和自動化腳本等模塊。 FreeScheduler 是一款輕量級且功能強大的定時任務調度庫,它支持臨時的延時任務和重覆迴圈任務(可持久化),能夠按秒、每天/每周/每月固定時間或自定義間隔執行(CRON 表達式)。 此外 ...
  • 目錄Blazor 組件基礎路由導航參數組件參數路由參數生命周期事件狀態更改組件事件 Blazor 組件 基礎 新建一個項目命名為 MyComponents ,項目模板的交互類型選 Auto ,其它保持預設選項: 客戶端組件 (Auto/WebAssembly): 最終解決方案裡面會有兩個項目:伺服器 ...
  • 先看一下效果吧: isChecked = false 的時候的效果 isChecked = true 的時候的效果 然後我們來實現一下這個效果吧 第一步:創建一個空的wpf項目; 第二步:在項目裡面添加一個checkbox <Grid> <CheckBox HorizontalAlignment=" ...
  • 在編寫上位機軟體時,需要經常處理命令拼接與其他設備進行通信,通常對不同的命令封裝成不同的方法,擴展稍許麻煩。 本次擬以特性方式實現,以兼顧維護性與擴展性。 思想: 一種命令對應一個類,其類中的各個屬性對應各個命令段,通過特性的方式,實現其在這包數據命令中的位置、大端或小端及其轉換為對應的目標類型; ...