路径参数
路径参数是URL路径的一部分,用于标识特定的资源。在FastAPI中,可以通过在路径中使用花括号
{}
来定义路径参数,并在函数参数中指定其类型。
python
@app.get("/items/{item_id}")
async def read_item(item_id: int): #如果不指定,默认是str类型。这里实际上进行了类型转换,如果转换失败会返回400错误
return {"item_id": item_id}
路由匹配顺序
python
app01 = APIRouter()
@app01.get("/user/1")
async def get_users():
return {"userid": "root_user"}
@app01.get("/user/{user_id}")
async def get_users(user_id):
print(f"user_id: {user_id}")
return {"userid": user_id}
#运行后输入user_id为1时,访问的是第一个接口,输出{"userid": "root_user"}
#因为路径是从上到下匹配的,顺序很重要
查询参数
函数中声明不属于路径参数的其他函数参数时,他们会自动解释为"查询字符串"参数
python
@app02.get("/jobs/{kd}")
async def get_jobs(kd: str, xl: str, gj: str):
#基于查询参数的业务逻辑处理
return {
"kd": kd,
"xl": xl,
"gj": gj
}
#访问路径示例:/jobs/关键字?xl=本科&gj=3-5年
如果查询参数是可选的
python
@app02.get("/jobs/{kd}")
async def get_jobs(kd: str, xl: str = None, gj: str = None):#或者 xl: str | None = None
#基于查询参数的业务逻辑处理
return {
"kd": kd,
"xl": xl,
"gj": gj
}
#访问路径示例:/jobs/关键字?xl=本科
请求体数据
请求体数据通常用于POST、PUT等请求方法中,携带需要创建或更新的数据。在FastAPI中,可以使用Pydantic模型来定义请求体的数据结构。
python
from pydantic import BaseModel, Field
from datetime import date
from typing import List, Union
from datetime import datetime
app03= APIRouter()
class User(BaseModel):#BaseModel是Pydantic提供的基类,作用是数据验证和序列化
name: str = "张三"
age: int = Field(default=0, gt=0, lt=100)
bir: Union[date, None] = Field(default=None)
friends: List[int] = []
description: None | str = None
@app03.post("/data")
async def post_data(data: User):
print(data.model_dump())
return data
说明:
- 使用Pydantic的BaseModel定义了一个User模型,包含name、age、bir、friends和description字段。
- age字段使用Field进行了更详细的验证,要求其值在0到100之间
- 在路径操作函数post_data中,data参数的类型是User,这表示请求体的数据将被解析为User模型的实例。
- 当客户端发送POST请求到/data路径时,FastAPI会自动将请求体的数据解析为User模型,并进行验证。如果数据有效,函数将返回该User实例,否则会返回400错误,说明请求体数据不符合预期格式。
- data.model_dump()方法用于将Pydantic模型实例转换为字典格式,方便查看和处理数据。
python
class User(BaseModel):
name: str = "张三"
age: int = Field(default=0, gt=0, lt=100)
bir: Union[date, None] = Field(default=None)
friends: List[int] = []
description: None | str = None
@field_validator("bir")
def check_bir(cls, v):
if v and v > date.today():
raise ValueError("生日不能大于今天的日期")
return v
说明:
- 使用@field_validator装饰器为bir字段添加了一个自定义验证器。
- 验证器函数check_bir接受两个参数:cls表示模型类本身,v表示要验证的字段值。
- 在验证器中,首先检查v是否存在且是否大于今天的日期。如果是,则抛出一个ValueError异常,提示生日不能大于今天的日期。
- 如果验证通过,返回字段值v。
表单数据
表单数据通常用于HTML表单提交的数据。在FastAPI中,可以使用Form类来定义表单字段。
在OAuth2规范的一种使用方式(密码模式)中,客户端通过表单数据提交用户名和密码以获取访问令牌,而不是通过JSON请求体。
FastAPI可以使用Form组件来接受表单数据
python
app04= APIRouter()
@app04.post("/register")
async def register(username: str = Form(...), password: str = Form()):
print(f"用户名:{username},密码:{password}")
#实现注册的业务逻辑
return {
"username": username
}
文件上传
文件上传通常用于将文件从客户端发送到服务器。在FastAPI中,可以使用File和UploadFile类来处理文件上传。
使用File类上传文件
python
@app05.post("/file")
async def get_file(files: bytes = File()):
#适合小文件上传
print(f"file", files)
return {"file": len(files)}
@app05.post("/files")#多文件上传
async def get_files(files: List[bytes] = File()):
for f in files:
print(f"file", len(f))
return {"files": len(files)}
使用UploadFile类上传文件
python
@app05.post("/uploadfile")#适合大文件上传
async def upload_file(file: UploadFile):
print("file:",file)
path = os.path.join("dir", file.filename)
with open(path,"wb") as f:
for line in file.file:
f.write(line)
return {
"file": file.filename
}
@app05.post("/uploadfiles")#多文件上传
async def upload_files(files: List[UploadFile]):
for file in files:
path = os.path.join("dir", file.filename)
with open(path,"wb") as f:
for line in file.file:
f.write(line)
return {
"files": [file.filename for file in files]
}
使用File类 时,文件内容会被读取为字节 数据,适合小文件上传。而使用UploadFile类 时,文件内容以流的形式处理,适合大文件上传,可以避免将整个文件加载到内存中。
Request对象
Request对象表示HTTP请求的所有信息,包括请求头、请求体、查询参数等。在FastAPI中,可以通过在路径操作函数中添加Request参数来访问Request对象。
python
@app06.post("/request")
async def Request_info(request: Request):
print("URL:", request.url)
print("客户端ip:", request.client.host)
print("客户端宿主:", request.headers.get("user-agent"))
print("cookies:", request.cookies)#cookies 是一个字典,用处是存储用户相关信息
return {
"url": str(request.url),
"客户端ip": request.client.host,
"客户端宿主": request.headers.get("user-agent"),
"cookies": request.cookies
}
请求静态文件
静态文件 是指不需要服务器动态生成 的文件,如HTML、CSS、JavaScript、图片等。在FastAPI中,可以使用StaticFiles类来处理静态文件的请求。
动态文件 是指需要服务器动态生成的文件,如通过模板引擎生成的HTML页面。在FastAPI中,可以使用Jinja2Templates类来处理动态文件的请求。
python
from fastapi import FastAPI,staticfiles
app = FastAPI()
app.mount("/static", staticfiles.StaticFiles(directory="static"))
- 通过app.mount()方法将/static路径映射到本地的static目录。
- 当客户端请求/static路径下的文件时,FastAPI会从static目录中查找对应的文件并返回给客户端。
响应模型相关的参数
FastAPI允许我们自定义响应模型,以控制返回给客户端的数据结构和格式。
- 前面写得这么多路径函数返回的都是自定义结构的字典数据,FastAPI提供了response_model参数,可以指定响应模型,从而自动将返回的数据转换为指定的模型格式。
python
class UserIn(BaseModel):
username:str
password:str
email:EmailStr
full_name:Union[str,None]=None
class UserOut(BaseModel):
username:str
email:EmailStr
full_name:Union[str,None]=None
@app07.post("/user",response_model=UserOut)
async def create_user(user: UserIn):
# 模拟将用户信息存储到数据库
return user
- 在上面的代码中,定义了两个Pydantic模型UserIn和UserOut,分别表示输入和输出的数据结构。
- 在路径操作函数create_user中,使用response_model参数指定响应模型为UserOut。
- response_model_exclude_unset:排除未设置的字段
python
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: List[str] = []
items={
"item1": Item(name="Item One", price=10.0),
"item2": Item(name="Item Two", description="The second item", price=20.0, tax=2.0, tags=["tag3", "tag4"]),
}
@app07.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
- 在上面的代码中,定义了一个Item模型,包含多个字段。
- 在路径操作函数read_item中,使用response_model_exclude_unset=True参数,表示在响应中排除未设置的字段。
- 当客户端请求/item1时,响应只包含name和price字段,而description、tax和tags字段将被排除,因为它们未设置。