还在为构建高性能API而烦恼?知道吗,FastAPI 框架的性能与NodeJS和Go相当,同时提供极佳的开发体验。
📖 文章摘要
本文带你快速上手FastAPI的请求与响应处理核心。你将清晰地掌握如何定义路由、处理GET/POST请求、玩转查询与路径参数、管理请求头与响应头、解析表单数据以及实现页面重定向。文末附有可直接运行的完整代码示例。
🚀 你将学到:
-
路由与请求方法的基础定义
-
如何接收查询参数和路径参数
-
处理POST请求与JSON数据
-
读取请求头与设置自定义响应头
-
解析application/x-www-form-urlencoded表单数据
-
实现简单的重定向响应
✨ 目录
-
🛣️ 第一步:从路由与请求方法开始
-
🔍 GET请求:查询参数与路径参数
-
📤 POST请求:接收JSON与表单数据
-
📨 请求头与响应头:细节控制
-
↪️ 重定向:让请求跳转起来
-
💻 完整代码示例:一个迷你API服务
🛣️ 第一步:从路由与请求方法开始
在FastAPI中,一切从app实例和装饰器开始。@app.get()、@app.post()等装饰器定义了URL路径和HTTP方法。
from fastapi import FastAPI
app = FastAPI()
# 定义一个处理根路径GET请求的路由
@app.get("/")
def read_root():
return {"message": "Hello, FastAPI World!"}
# 定义一个处理'/items'路径GET请求的路由
@app.get("/items/")
def read_items():
return [{"item_id": 1, "name": "Foo"}]
看,就这么简单!每个函数对应一个API端点,返回值自动转换为JSON响应。
🔍 GET请求:查询参数与路径参数
GET请求常用于获取数据,参数通常通过URL传递。主要有两种方式:查询参数 和路径参数。
查询参数 :跟在URL问号?后面,如/items/?skip=0&limit=10。在函数参数中声明即可自动获取。
@app.get("/items/")
def read_items(skip: int = 0, limit: int = 10):
# 模拟从数据库读取数据
fake_items = [{"item_id": i} for i in range(skip, skip + limit)]
return fake_items
路径参数 :直接嵌在URL路径中,如/items/123。在路由中用{}声明。
@app.get("/items/{item_id}")
def read_item(item_id: int): # 类型注解会自动进行验证和转换
return {"item_id": item_id, "name": f"Item {item_id}"}
FastAPI的类型提示功能会帮你自动验证参数类型,并提供漂亮的API文档!
📤 POST请求:接收JSON与表单数据
POST请求用于创建或提交数据。最常见的是接收JSON 和表单数据。
1. 接收JSON数据:使用Pydantic模型来定义数据结构。
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.post("/items/")
def create_item(item: Item): # 将请求体声明为Item类型
# 可以直接使用item的属性
item_dict = item.dict()
if item.tax:
total_price = item.price + item.tax
item_dict.update({"total_price": total_price})
return item_dict
2. 接收表单数据 :当数据来自HTML表单时,使用Form。
from fastapi import Form
@app.post("/login/")
def login(username: str = Form(...), password: str = Form(...)):
# Form(...)表示必填字段
return {"username": username, "login_status": "success"}
注意:使用Form前需要先安装python-multipart库。
📨 请求头与响应头:细节控制
有时你需要读取客户端的请求头,或者为响应添加自定义头部信息。
读取请求头 :使用Header函数。
from fastapi import Header
@app.get("/headers/")
def read_headers(user_agent: str | None = Header(None)):
return {"User-Agent": user_agent}
设置响应头 :返回一个Response对象,或在依赖中设置。
from fastapi import Response
@app.get("/custom-header/")
def set_custom_header(response: Response):
response.headers["X-Custom-Header"] = "MyCustomValue"
return {"message": "Check the headers!"}
↪️ 重定向:让请求跳转起来
重定向在Web开发中很常见,比如登录后跳转到首页。使用RedirectResponse即可轻松实现。
from fastapi.responses import RedirectResponse
@app.get("/old-link/")
def old_link():
# 永久重定向到新的URL
return RedirectResponse(url="/new-link/", status_code=301)
@app.get("/new-link/")
def new_link():
return {"message": "This is the new endpoint!"}
💻 完整代码示例:一个迷你API服务
将上面的知识点整合,创建一个简单的笔记API。保存为main.py,然后用uvicorn main:app --reload运行它!
from fastapi import FastAPI, Path, Query, Header, Form, Response
from fastapi.responses import RedirectResponse
from pydantic import BaseModel
from typing import Optional
app = FastAPI(title="迷你笔记API")
# 数据模型
class Note(BaseModel):
title: str
content: str
# 模拟数据库
fake_notes_db = [{"id": 1, "title": "First Note", "content": "Hello!"}]
# 首页重定向到文档
@app.get("/")
def home():
return RedirectResponse(url="/docs")
# 获取所有笔记 (带查询参数分页)
@app.get("/notes/")
def get_notes(skip: int = Query(0, ge=0), limit: int = Query(10, le=100)):
return fake_notes_db[skip : skip + limit]
# 根据ID获取特定笔记 (路径参数)
@app.get("/notes/{note_id}")
def get_note_by_id(note_id: int = Path(..., title="笔记ID", gt=0)):
for note in fake_notes_db:
if note["id"] == note_id:
return note
return {"error": "Note not found"}
# 创建新笔记 (POST JSON)
@app.post("/notes/")
def create_note(note: Note, response: Response):
new_id = max([n["id"] for n in fake_notes_db], default=0) + 1
new_note = {"id": new_id, **note.dict()}
fake_notes_db.append(new_note)
response.headers["Location"] = f"/notes/{new_id}"
response.status_code = 201
return new_note
# 一个需要User-Agent头的端点
@app.get("/check-agent/")
def check_user_agent(user_agent: Optional[str] = Header(None)):
return {"received_user_agent": user_agent}
# 表单登录示例
@app.post("/login-form/")
def login_form(username: str = Form(...), password: str = Form(...)):
# 这里应该有真实的验证逻辑
if username == "admin" and password == "secret":
return {"message": "Login successful"}
return {"message": "Invalid credentials"}
启动后,访问 http://127.0.0.1:8000/docs 即可看到交互式API文档,并直接测试所有端点!
喜欢本文?不要错过✨,点赞👍收藏⭐关注我👆,一起学习更多有用的知识,完善你我的技能树!