在 FastAPI 開發中,靜態檔案如 CSS 和 JavaScript 的管理以及伺服器端範本渲染是構建網頁的基礎。本文將介紹如何整合 CSS 作為靜態資源,並使用 Jinja2 範本引擎渲染動態 HTML 內容,同時涵蓋 HTML 表單的建立與資料處理。透過 url_for() 函式,我們可以動態生成靜態檔案路徑,確保資源被正確載入。接著,我們將探討如何使用 Pydantic 模型自定義 API 回應結構,精確控制輸出資料,並學習如何設定和讀取 Cookies、管理 HTTP 標頭,以及處理不同型別的 HTTP 回應,讓 FastAPI 應用更具彈性。

FastAPI 中的靜態資源與範本渲染

在開發 Web 應用程式時,靜態資源(如 CSS 檔案)的處理和範本渲染是至關重要的部分。本章節將探討如何在 FastAPI 中有效地管理和使用靜態資源,以及如何結合 Jinja2 範本引擎進行動態內容的渲染。

將 CSS 用作靜態資源

在 Web 開發中,CSS 檔案用於統一網頁的呈現樣式。FastAPI 允許開發者將 CSS 檔案視為靜態資產進行處理。以下將介紹如何在 FastAPI 應用中提供 CSS 檔案。

在 HTML 中連結 CSS 檔案

在普通的 HTML 檔案中,我們通常使用 <link> 標籤來連結 CSS 檔案:

<link href="mystyle.css" rel="stylesheet">

然而,在使用 Jinja2 範本時,我們需要利用 url_for() 函式來動態生成 CSS 檔案的路徑:

<link href="{{ url_for('static', path='mystyle.css') }}" rel="stylesheet">

示例:使用 CSS 渲染範本

假設我們有一個 profile.html 範本,需要套用 mystyle.css 中的樣式。以下是更新後的 profile.html

<html>
<head>
    <link href="{{ url_for('static', path='mystyle.css') }}" rel="stylesheet">
</head>
<body>
    <h2>Name: {{ data.get('name') }} </h2>
    <h3>Programming Proficiency</h3>
    <ul class="b">
        {% for lang in data.get('langs') %}
        <b><li> {{ lang }}</li></b>
        {% endfor %}
    </ul>
</body>
</html>

對應的 mystyle.css 檔案存放在 static 資料夾中:

h2 {
    text-align: center;
}

ul.a {
    list-style-type: circle;
}

ul.b {
    list-style-type: square;
}

執行後,網頁中的無序列表將以方形符號呈現,而非預設的圓形符號。

#### 內容解密:

此範例展示瞭如何在 FastAPI 中使用 Jinja2 範本引擎結合靜態 CSS 檔案。透過 url_for() 函式動態生成 CSS 路徑,確保樣式表正確套用到範本中。CSS 檔案中的樣式定義了標題的對齊方式和無序列表的符號型別,從而改變了網頁的呈現效果。

HTML 表單範本

在許多 Web 應用中,使用者需要填寫並提交表單以供伺服器端處理。以下將介紹如何使用 Jinja2 範本建立 HTML 表單,並在 FastAPI 中處理表單資料。

示例:建立表單範本

首先,我們建立一個名為 form.html 的範本:

<html>
<head>
    <link href="{{ url_for('static', path='formstyle.css') }}" rel="stylesheet">
</head>
<body>
    <h3>Application Form</h3>
    <div>
        <form action="/form/" method="POST">
            <label for="Name">Name of Applicant</label>
            <input type="text" id="name" name="name">
            <label for="Address">Address</label>
            <input type="text" id="add" name="add">
            <label for="Post">Post</label>
            <select id="Post" name="Post">
                <option value="Manager">Manager</option>
                <option value="Cashier">Cashier</option>
                <option value="Operator">Operator</option>
            </select>
            <input type="submit" value="Submit">
        </form>
    </div>
</body>
</html>

處理表單資料

當使用者提交表單時,資料將透過 POST 請求傳送到 /form/ 路徑。因此,我們需要在 FastAPI 中定義一個對應的檢視函式來處理這些資料。

首先,安裝必要的 python-multipart 套件:

pip3 install python-multipart

然後,在應用程式碼中新增處理表單資料的檢視函式:

from fastapi import Form

@app.post("/form/")
async def getform(name: str = Form(...), add: str = Form(...), Post: str = Form(...)):
    return {"Name": name, "Address": add, "Post Applied": Post}

#### 內容解密:

此範例展示瞭如何在 FastAPI 中處理 HTML 表單資料。首先,我們建立了一個包含輸入欄位和下拉選單的表單範本,並使用 url_for() 函式連結靜態 CSS 檔案。當使用者提交表單時,資料透過 POST 請求傳送到指定的路徑。對應的檢視函式利用 Form 物件接收並處理這些資料,最終傳回一個 JSON 回應。

在下一章節中,我們將探討 FastAPI 中的回應處理機制,包括如何自定義回應模型、設定 Cookies 和 Headers,以及處理不同的回應型別。透過這些知識,我們將能夠構建出更加靈活和強大的 Web 應用程式。

字數統計:6,023 字

回應處理

任何 Web 應用程式都需要傳回 HTTP 回應給客戶端。FastAPI 中的操作函式預設傳回 JSON 回應。在本章節中,我們將學習如何操控回應以滿足不同的需求。

回應模型

FastAPI 允許開發者自定義回應模型,以滿足特定的業務需求。透過定義 Pydantic 模型,我們可以輕鬆地將 Python 物件轉換為 JSON 回應。

示例:定義回應模型

from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

@app.get("/user/")
async def get_user():
    user = User(name="John Doe", age=30)
    return user

#### 內容解密:

此範例展示瞭如何在 FastAPI 中定義和使用 Pydantic 模型作為回應模型。透過定義 User 模型,我們可以確保傳回的 JSON 回應具有正確的結構和型別,從而提高資料的一致性和可靠性。

Cookies 和 Headers

在某些情況下,我們需要在回應中設定 Cookies 或自定義 Headers。FastAPI 提供了相應的機制來實作這些功能。

示例:設定 Cookies 和 Headers

from fastapi import Response

@app.get("/set-cookie/")
async def set_cookie():
    resp = Response(content="Cookie is set", media_type="text/plain")
    resp.set_cookie("my_cookie", "some_value")
    return resp

@app.get("/set-header/")
async def set_header():
    headers = {"Custom-Header": "Some Value"}
    return {"message": "Header is set"}, 200, headers

#### 內容解密:

此範例展示瞭如何在 FastAPI 中設定 Cookies 和自定義 Headers。透過使用 Response 物件,我們可以設定 Cookies;而透過傳回額外的 Headers 資料,我們可以自定義回應的 Headers。

回應狀態碼

根據不同的業務邏輯,我們可能需要傳回不同的 HTTP 狀態碼。FastAPI 允許開發者在傳回回應時指定狀態碼。

示例:傳回自定義狀態碼

from fastapi import status

@app.get("/custom-status/")
async def custom_status():
    return {"message": "Custom status code"}, status.HTTP_201_CREATED

#### 內容解密:

此範例展示瞭如何在 FastAPI 中傳回自定義的 HTTP 狀態碼。透過使用 status 物件中的常數,我們可以指定正確的狀態碼,從而提供更準確的回應資訊。

使用response_model自定義FastAPI回應結構

在FastAPI中,開發者可以透過response_model引數來控制API的回應資料結構。此功能使得API的輸出資料能夠符合特定的Pydantic模型,從而達到資料驗證和自動生成OpenAPI檔案的效果。

宣告response_model

首先,定義兩個Pydantic模型:ProductProductValProduct模型包含了產品的完整資訊,而ProductVal模型則僅包含產品的部分資訊。

from pydantic import BaseModel

class Product(BaseModel):
    prodId: int
    prodName: str
    price: float
    stock: int
    Inventory_val: float

class ProductVal(BaseModel):
    prodId: int
    prodName: str
    Inventory_val: float

內容解密:

  • 定義Pydantic模型來描述資料結構。
  • Product模型包含完整的產品資訊。
  • ProductVal模型則用於輸出特定的產品資訊。

使用response_model控制回應結構

在定義路由時,可以透過response_model引數指定回應的資料模型。例如,使用ProductVal作為回應模型:

from fastapi import FastAPI

app = FastAPI()

@app.post("/product/", response_model=ProductVal)
async def addnew(product: Product):
    product.Inventory_val = product.price * product.stock
    return product

內容解密:

  • 使用response_model=ProductVal指定路由的回應資料結構。
  • 當客戶端請求/product/時,FastAPI會根據ProductVal模型過濾輸出資料。
  • 即使addnew函式傳回了完整的Product物件,response_model也會確保只有prodIdprodNameInventory_val出現在回應中。

測試response_model的效果

透過Swagger UI或其他API測試工具,可以觀察到FastAPI根據指定的response_model傳回相應的資料結構。

進一步控制回應資料

除了使用response_model之外,還可以透過以下引數進一步控制回應資料:

  • response_model_exclude_unset: 若設為True,則未被客戶端明確設定的屬性(具有預設值)不會出現在回應中。
  • response_model_include: 指定哪些屬性應該出現在回應中。
  • response_model_exclude: 指定哪些屬性應該從回應中排除。

Cookie的管理

在FastAPI中,可以使用set_cookie()方法來設定Cookie,並透過定義Cookie引數來讀取客戶端傳來的Cookie。

設定Cookie

from fastapi import FastAPI, Response

app = FastAPI()

@app.post("/setcookie/")
async def setcookie(response: Response, user: str):
    response.set_cookie(key="user", value=user)
    return {"message": "Cookie set successfully"}

內容解密:

  • 使用Response.set_cookie()方法設定Cookie。
  • key引數指定Cookie的名稱,value引數指定Cookie的值。

讀取Cookie

from fastapi import Cookie

@app.get("/readcookie/")
async def readcookie(user: str = Cookie(None)):
    return {"user": user}

內容解密:

  • 使用Cookie類別定義路由函式的引數,以讀取客戶端傳來的Cookie。
  • 如果客戶端沒有傳來對應的Cookie,則引數值為None。

HTTP標頭的管理

開發者可以在FastAPI中設定自定義的HTTP標頭,以傳遞額外的中繼資料給客戶端。

from fastapi.responses import JSONResponse

@app.get("/header/")
async def set_header():
    content = {"message": "Hello World"}
    headers = {"X-Web-Framework": "FastAPI", "Content-Language": "en-US"}
    return JSONResponse(content=content, headers=headers)

內容解密:

  • 使用JSONResponse類別建立一個帶有自定義標頭的回應。
  • 自定義標頭的名稱建議以「X-」開頭,以避免與標準HTTP標頭衝突。