FastAPI 作為一個高效能的 Python Web 框架,在建構 API 時展現出其優勢。其簡潔的語法和豐富的功能,讓開發者能更快速地開發和佈署 API 服務。理解 FastAPI 的引數設定、錯誤處理機制和請求回應管理,是開發穩健且高效 API 的關鍵。透過妥善運用這些技術,可以確保 API 的穩定性、可靠性和易維護性,進而提升整體開發效率。在實際應用中,根據專案需求選擇合適的引數型別、錯誤處理策略和回應資料格式,能讓 API 更符合預期,並提供更好的使用者經驗。

程式碼解說

上述程式碼使用 FastAPI 框架實作使用者驗證和授權。使用 Optional 型別來定義選擇性引數,使用 hashpw 函式來驗證密碼。Mermaid 圖表展示了使用者驗證和授權的流程。

FastAPI 引數設定與錯誤處理

在使用 FastAPI 框架開發 API 服務時,瞭解如何設定引數和進行錯誤處理是非常重要的。下面我們將探討如何在 FastAPI 中設定不同型別的引數,包括可選引數、必需引數和預設值引數,並且如何使使用案例外處理和防禦性驗證來避免 HTTP 狀態 500(內部伺服器錯誤)。

可選引數

在 FastAPI 中,你可以使用 Optional 型別來宣告可選引數。例如:

from typing import Optional
from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{username}")
def read_user(username: str, id: Optional[int] = None):
    if id is None:
        return {"message": "id is not provided"}
    # ...

在這個例子中,id 引數是可選的,如果沒有提供 id,則會傳回一條訊息。

必需引數

必需引數可以直接宣告為特定型別,例如:

from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{username}")
def read_user(username: str, id: int):
    # ...

在這個例子中,id 引數是必需的,如果沒有提供 id,則會傳回一個錯誤。

預設值引數

你可以使用 = 來設定預設值引數,例如:

from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{username}")
def read_user(username: str, new_names: dict = {}):
    # ...

在這個例子中,new_names 引數有一個預設值為空字典。

混合引數

FastAPI 支援混合使用不同型別的引數,例如:

from typing import Optional
from fastapi import FastAPI

app = FastAPI()

@app.patch("/ch01/account/profile/update/names/{username}")
def update_profile_names(id: int, username: str = '', new_names: Optional[dict] = None):
    if valid_users.get(username) is None:
        return {"message": "user does not exist"}
    elif new_names is None:
        return {"message": "new names are required"}
    else:
        user = valid_users.get(username)
        if user.id == id:
            # ...

在這個例子中,id 引數是必需的,username 引數有一個預設值,new_names 引數是可選的。

錯誤處理

FastAPI 提供了強大的錯誤處理機制,你可以使用 try-except 區塊來捕捉和處理異常。例如:

from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{username}")
def read_user(username: str):
    try:
        user = valid_users.get(username)
        if user is None:
            raise ValueError("user does not exist")
        # ...
    except ValueError as e:
        return {"message": str(e)}

在這個例子中,如果 username 不存在,則會傳回一條錯誤訊息。

防禦性驗證

FastAPI 也提供了防禦性驗證機制,你可以使用 validate 函式來驗證輸入引數。例如:

from fastapi import FastAPI, validate

app = FastAPI()

@app.get("/users/{username}")
def read_user(username: str):
    validate(username, "username is required")
    # ...

在這個例子中,如果 username 是空的,則會傳回一條錯誤訊息。

圖表翻譯:

  graph LR
    A[開始] --> B[驗證輸入引數]
    B --> C[執行業務邏輯]
    C --> D[傳回結果]
    D --> E[錯誤處理]
    E --> F[傳回錯誤訊息]

在這個圖表中,我們可以看到 FastAPI 的錯誤處理和防禦性驗證機制的流程。

使用 FastAPI 處理使用者請求和伺服器回應

在 FastAPI 中,管理使用者請求和伺服器回應是一個重要的方面。下面我們將探討如何使用 FastAPI 來更新使用者個人資料。

更新使用者個人資料

首先,我們需要定義一個路由來處理使用者個人資料的更新。這個路由需要接受使用者的使用者名稱、UUID id 和新的名字資訊。

from fastapi import FastAPI, Path, Query
from pydantic import BaseModel
from typing import Optional
from datetime import date

app = FastAPI()

class UserProfile(BaseModel):
    firstname: str
    lastname: str
    middle_initial: str
    age: Optional[int] = 0
    salary: Optional[int] = 0
    birthday: date
    user_type: str

valid_profiles = {}

@app.put("/users/{username}")
async def update_profile_names(
    username: str = Path(..., title="The username of the user"),
    id: str = Query(..., title="The UUID id of the user"),
    new_names: dict = {"fname": "", "lname": "", "mi": ""}
):
    if username in valid_profiles:
        profile = valid_profiles[username]
        profile.firstname = new_names['fname']
        profile.lastname = new_names['lname']
        profile.middle_initial = new_names['mi']
        valid_profiles[username] = profile
        return {"message": "successfully updated"}
    else:
        return {"message": "user does not exist"}

請求體

在 FastAPI 中,請求體是使用者傳送給伺服器的資料。要處理請求體,需要定義一個模型類別來代表和捕捉請求體。

from pydantic import BaseModel

class User(BaseModel):
    username: str
    password: str

class UserProfile(BaseModel):
    firstname: str
    lastname: str
    middle_initial: str
    age: Optional[int] = 0
    salary: Optional[int] = 0
    birthday: date
    user_type: str

結合使用

現在,我們可以結合使用路由和模型類別來處理使用者請求和伺服器回應。

from fastapi import FastAPI, Path, Query, Body
from pydantic import BaseModel
from typing import Optional
from datetime import date

app = FastAPI()

class UserProfile(BaseModel):
    firstname: str
    lastname: str
    middle_initial: str
    age: Optional[int] = 0
    salary: Optional[int] = 0
    birthday: date
    user_type: str

valid_profiles = {}

@app.put("/users/{username}")
async def update_profile_names(
    username: str = Path(..., title="The username of the user"),
    id: str = Query(..., title="The UUID id of the user"),
    new_names: UserProfile = Body(..., title="The new names of the user")
):
    if username in valid_profiles:
        profile = valid_profiles[username]
        profile.firstname = new_names.firstname
        profile.lastname = new_names.lastname
        profile.middle_initial = new_names.middle_initial
        valid_profiles[username] = profile
        return {"message": "successfully updated"}
    else:
        return {"message": "user does not exist"}

圖表翻譯

此圖示為更新使用者個人資料的流程圖。

  flowchart TD
    A[開始] --> B[使用者傳送請求]
    B --> C[伺服器接收請求]
    C --> D[伺服器處理請求]
    D --> E[伺服器傳回回應]
    E --> F[使用者接收回應]

此圖表翻譯為更新使用者個人資料的流程。首先,使用者傳送請求給伺服器,然後伺服器接收請求並處理它,最後伺服器傳回回應給使用者。

FastAPI 入門

FastAPI 是一個現代化的 Python Web 框架,旨在提供快速、簡單和高效的 API 開發體驗。以下是使用 FastAPI 的基本步驟和範例。

安裝 FastAPI

首先,您需要安裝 FastAPI。您可以使用 pip 安裝:

pip install fastapi

建立模型

在 FastAPI 中,您可以使用 Pydantic 建立模型。Pydantic 是一個強大的模型函式庫,允許您定義模型的屬性和行為。以下是建立模型的範例:

from pydantic import BaseModel
from typing import Optional, List
from uuid import UUID
from datetime import datetime

class ForumPost(BaseModel):
    id: UUID
    topic: Optional[str] = None
    message: str
    post_type: str
    date_posted: datetime
    username: str

class ForumDiscussion(BaseModel):
    id: UUID
    main_post: ForumPost
    replies: Optional[List[ForumPost]] = None
    author: str

在這個範例中,我們定義了兩個模型:ForumPostForumDiscussionForumPost 模型有五個屬性:idtopicmessagepost_typedate_postedForumDiscussion 模型有四個屬性:idmain_postrepliesauthor

建立 API 端點

接下來,您需要建立 API 端點。以下是建立 API 端點的範例:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

@app.post("/ch01/login/validate", response_model=ValidUser)
def approve_user(user: User):
    if not valid_users.get(user.username) == None:
        return ValidUser(id=None, username=None, password=None, passphrase=None)
    else:
        valid_user = ValidUser(id=uuid1(), username=user.username, password=user.password, passphrase=hashpw(user.password.encode(), gensalt()))
        return valid_user

在這個範例中,我們建立了一個 API 端點 /ch01/login/validate,該端點接受一個 User 物件作為請求體。該端點使用 response_model 引數指定傳回的模型型別為 ValidUser

處理請求和回應

FastAPI 提供了一個簡單的方式來處理請求和回應。您可以使用 request 物件來存取請求資料,使用 response 物件來傳回回應資料。以下是處理請求和回應的範例:

from fastapi import Request, Response

@app.post("/ch01/login/validate")
def approve_user(request: Request):
    user_data = request.json()
    # 處理使用者資料
    return Response(content="使用者驗證成功", media_type="text/plain")

在這個範例中,我們使用 Request 物件來存取請求資料,使用 Response 物件來傳回回應資料。

FastAPI 基礎設定與請求頭處理

FastAPI 是一種現代化的 Python Web 框架,能夠快速地建構 API 服務。下面將介紹如何設定 FastAPI 以及如何處理請求頭。

FastAPI 基礎設定

首先,需要安裝 FastAPI 和 uvicorn。可以使用 pip 安裝:

pip install fastapi uvicorn

然後,建立一個新的 Python 檔案,例如 main.py,並加入以下程式碼:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello, World!"}

這是一個基本的 FastAPI 應用程式,當您存取 / 路由時,會傳回一個 JSON 物件。

請求頭處理

FastAPI 提供了一種簡單的方式來存取請求頭。您可以使用 Header 函式來宣告一個變數,然後使用這個變數來存取請求頭的值。

例如,以下程式碼展示瞭如何存取 User-Agent 請求頭:

from fastapi import FastAPI, Header

app = FastAPI()

@app.get("/headers/")
def read_headers(user_agent: str = Header(None)):
    return {"user_agent": user_agent}

在這個例子中,user_agent 變數被宣告為一個可選的字串,然後使用 Header 函式來初始化它。當您存取 /headers/ 路由時,會傳回一個 JSON 物件,包含 User-Agent 請求頭的值。

處理多個請求頭

您也可以存取多個請求頭,方法是宣告多個變數,然後使用 Header 函式來初始化它們。

例如,以下程式碼展示瞭如何存取 HostAcceptAccept-LanguageAccept-Encoding 請求頭:

from fastapi import FastAPI, Header
from typing import Optional

app = FastAPI()

@app.get("/headers/")
def read_headers(
    host: Optional[str] = Header(None),
    accept: Optional[str] = Header(None),
    accept_language: Optional[str] = Header(None),
    accept_encoding: Optional[str] = Header(None)
):
    return {
        "host": host,
        "accept": accept,
        "accept_language": accept_language,
        "accept_encoding": accept_encoding
    }

在這個例子中,宣告了四個變數,然後使用 Header 函式來初始化它們。當您存取 /headers/ 路由時,會傳回一個 JSON 物件,包含這四個請求頭的值。

管理使用者請求和伺服器回應

在 FastAPI 中,管理使用者請求和伺服器回應是一個重要的議題。以下是如何使用 FastAPI 來管理使用者請求和伺服器回應的範例。

請求標頭

首先,讓我們來看看如何設定請求標頭。請求標頭是用來提供額外的資訊給伺服器,例如使用者代理、語言偏好等。

from fastapi import FastAPI, Header

app = FastAPI()

@app.get("/items/")
def read_items(
    host: str = Header(None),
    accept: str = Header(None),
    accept_language: str = Header(None),
    accept_encoding: str = Header(None),
    user_agent: str = Header(None)
):
    request_headers = {
        "Host": host,
        "Accept": accept,
        "Accept-Language": accept_language,
        "Accept-Encoding": accept_encoding,
        "User-Agent": user_agent
    }
    return request_headers

在這個範例中,我們使用 Header 函式來定義請求標頭。Header 函式的第一個引數是標頭的名稱,第二個引數是標頭的預設值。

回應資料

FastAPI 的 API 服務應該傳回 JSON 資料,否則可能會傳回 None。以下是如何使用 dictBaseModelJSONResponse 物件來形成回應資料的範例。

from fastapi import FastAPI, BaseModel, JSONResponse

app = FastAPI()

class Post(BaseModel):
    topic: str
    message: str
    post_type: str
    date_posted: str

@app.post("/ch01/discussion/posts/add/{username}")
def post_discussion(username: str, post: Post, post_type: str):
    if valid_users.get(username) is None:
        return {"message": "user does not exist"}
    elif discussion_posts.get(post.id) is not None:
        return {"message": "post already exists"}
    else:
        forum_post = ForumPost(
            id=uuid1(),
            topic=post.topic,
            message=post.message,
            post_type=post_type,
            date_posted=post.date_posted,
            username=username
        )
        user = valid_profiles[username]
        forum = ForumDiscussion(
            id=uuid1(),
            main_post=forum_post,
            author=user,
            replies=[]
        )
        discussion_posts[forum.id] = forum
        return {"message": "post created successfully"}

在這個範例中,我們使用 BaseModel 來定義 Post 物件,並使用 JSONResponse 來傳回 JSON 資料。

FastAPI 框架的基礎知識

FastAPI 是一種現代化的 Python Web 框架,旨在快速建構 API。它提供了強大的功能,包括自動 API 檔案生成、強大的型別系統和高效能。

FastAPI 的基本結構

FastAPI 的基本結構包括以下幾個部分:

  • 路由(Route):定義 API 的路徑和方法。
  • 服務(Service):處理 API 請求的邏輯。
  • 模型(Model):定義 API 的資料結構。

FastAPI 的型別系統

FastAPI 使用 Pydantic 來定義型別。Pydantic 是一種強大的型別系統,允許你定義複雜的資料結構。

FastAPI 的表單處理

FastAPI 提供了 Form 函式來處理表單資料。表單資料可以是字串、整數、浮點數數等型別。

FastAPI 提供了 Cookie 函式來處理 Cookie。

FastAPI 的 API 檔案生成

FastAPI 可以自動生成 API 檔案,包括 API 的路徑、方法、引數和回應。

從技術架構視角來看,FastAPI 框架以其簡潔易用和高效能著稱,本文深入探討了其引數設定、錯誤處理、請求與回應管理、以及基礎設定等關鍵導向。FastAPI 利用 Pydantic 的強大型別系統,讓開發者能清晰地定義資料結構,同時也簡化了表單和 Cookie 的處理流程。其自動生成的 API 檔案更大幅提升了開發效率。然而,FastAPI 仍存在一些限制,例如在處理複雜的非同步任務時,需要更謹慎地設計程式碼以避免效能瓶頸。對於追求開發速度和程式碼可讀性的專案,FastAPI 是一個值得推薦的框架。隨著社群的持續發展和功能的逐步完善,預計 FastAPI 將在 Python Web 框架領域扮演越來越重要的角色。對於希望提升 API 開發效率的團隊,建議深入學習 FastAPI 的進階特性,例如依賴注入和中介軟體,以更好地滿足專案需求。