在 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模型:Product
和ProductVal
。Product
模型包含了產品的完整資訊,而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
也會確保只有prodId
、prodName
和Inventory_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標頭衝突。