前面记录的是路径参数和查询参数的内容,那两种形式的数据都不算的发送的数据,都是存在路径中的数据,请求体是客户端发给接口的参数,不存在于路径中,本文就主要记录FastAPI中的请求体应用内容。
一个发送请求体的接口
# 创建一个数据模型
class Animal(BaseModel):
name:str
category:Optional[str] = None
age:int
# 模型声明为请求体参数
@app03.post("/stu03/responsebody/")
async def stu03_responsebody(animal:Animal):
return animal.dict()
首先定义一个基本模型,是基于
Pydantic
的,然后将接口的animal
参数声明为Animal
类型的参数,接口接收请求体后返回给客户端接收的请求体内容
同时声明请求体、路径参数、查询参数
@app03.put("/stu03/blend/{param}")
async def stu03_param_blend(
respose_param: Animal,
param:int = Path(default=52),
query_param:Optional[str] = None
):
return {"respose_param":respose_param,"param":param,"query_param":query_param}
上面的代码就声明了三个参数
respose_param
、param
、query_param
,分布代表请求体、路径参数、查询参数
- 如果在路径中也声明了该参数,它将被用作路径参数。
- 如果参数属于单一类型(比如
int
、float
、str
、bool
等)它将被解释为查询参数。- 如果参数的类型被声明为一个 Pydantic 模型,它将被解释为请求体。
请求体中嵌套多个参数
# 创建一个数据模型
# 使用 Pydantic 的 Field 在 Pydantic 模型内部声明校验和元数据。
class City(BaseModel):
country:str = "中国"
provence:str = Field(...,example = "四川") # Field可以定义请求体的格式和类型
citys: Optional[List] = None
population: int = Field(default=None,title="人口数",ge=1000)
# 请求体中多个参数
@app03.put("/stu03/morebody")
def stuo3_morebody(
animal:Animal, # 最开始定义的模型
city:City
):
return {"animal":animal,"city":city}
上面的请求体就包含两个参数,分别是
Animal
和City
,请求体如下:{ "animal": { "name": "string", "category": "string", "age": 0 }, "city": { "country": "中国", "provence": "四川", "citys": [ "string" ], "population": 1000 } }
请求体中嵌入单一类型参数
@app03.post("/stu03/importance")
def stu03_importance(
importance_param_int_query: int,
importance_param_int:int = Body(default=12)
):
return {"importance_param_int":importance_param_int,"importance_param_int_query":importance_param_int_query}
如同时声明请求体、路径参数、查询参数一节所述,如果有单一类型的参数,那么他将会被解析为查询参数,所以要将单一类型的参数嵌套进入请求体,就需要使用
Body
指示 FastAPI 将其作为请求体的另一个键进行处理;如上述代码,
importance_param_int_query
会被解析为查询参数,而importance_param_int
会被嵌套进入请求体;
请求体中嵌入单一参数
@app03.post("/stu03/oneparam")
def stuo3_oneparam(
param:City = Body(embed=True)
):
return param
与上一步不同,上一步是单一类型的参数,这里是单一参数,即只有一个参数,这个参数是自定义的模型类类型参数;
处理和不处理的区别就是请求体中是否会有参数名作为键,描述抽象的话,看下面的对比就好;
使用方法就是将
Body
的embed
参数设为True
即可;
# 设置过的
{
"param": {
"country": "中国",
"provence": "四川",
"citys": [
"string"
],
"population": 1000
}
}
# 未设置的
{
"country": "中国",
"provence": "四川",
"citys": [
"string"
],
"population": 1000
}
参数多层嵌套
class CityDevelop(BaseModel):
city:City
money:int = 666
campony:int = 888
class CityDevelopTarget(BaseModel):
citydevelop:CityDevelop
metro:int = 20
gdp:int = 50000
@app03.post("/stu03/multiple_param")
def stu03_multiple_param(
citydeveloptarget:CityDevelopTarget
):
return citydeveloptarget
这里CityDevelop嵌套了请求体中嵌套多个参数中的City模型,CityDevelopTarget嵌套了CityDevelop模型,请求体如下:
{
"citydevelop": {
"city": {
"country": "中国",
"provence": "四川",
"citys": [
"string"
],
"population": 1000
},
"money": 666,
"campony": 888
},
"metro": 20,
"gdp": 50000
}
纯列表的请求体
@app03.post("/stu03/bodylist")
def stu03_body_list(
ListCity:List[City]
):
return ListCity
如果需要请求体最外层是一个列表,直接在对应函数中声明类型即可
ListCity:List[City]
如果是多个参数,目前想到的办法就是先声明一个模型类进行嵌套了,没有找到什么方法或者函数;
[
{
"country": "中国",
"provence": "四川",
"citys": [
"string"
],
"population": 1000
}
]
源码
# -*- coding: utf-8 -*-
# @Time: 2022/11/25 16:47
# @Author: MinChess
# @File: stu03.py
# @Software: PyCharm
from fastapi import APIRouter,Path,Body
from pydantic import BaseModel,Field
from typing import List,Optional
app03 = APIRouter()
# 创建一个数据模型
class Animal(BaseModel):
name:str
category:Optional[str] = None
age:int
# 模型声明为请求体参数
@app03.post("/stu03/responsebody/")
async def stu03_responsebody(animal:Animal):
return animal.dict()
# 请求体 + 路径参数 + 查询参数
@app03.put("/stu03/blend/{param}")
async def stu03_param_blend(
respose_param: Animal,
param:int = Path(default=52),
query_param:Optional[str] = None
):
return {"respose_param":respose_param,"param":param,"query_param":query_param}
# 创建一个数据模型
# 使用 Pydantic 的 Field 在 Pydantic 模型内部声明校验和元数据。
class City(BaseModel):
country:str = "中国"
provence:str = Field(...,example = "四川") # Field可以定义请求体的格式和类型
citys: Optional[List] = None
population: int = Field(default=None,title="人口数",ge=1000)
# 请求体中多个参数
@app03.put("/stu03/morebody")
def stuo3_morebody(
animal:Animal,
city:City
):
return {"animal":animal,"city":city}
# 请求体中嵌入单一值
@app03.post("/stu03/importance")
def stu03_importance(
importance_param_int_query: int,
importance_param_int:int = Body(default=12)
):
return {"importance_param_int":importance_param_int,"importance_param_int_query":importance_param_int_query}
# 请求体中嵌入单一参数
@app03.post("/stu03/oneparam")
def stuo3_oneparam(
param:City = Body(embed=True)
):
return param
# 单一参数未在请求体中嵌入
@app03.post("/stu03/notoneparam")
def stuo3_notoneparam(
param:City
):
return param
# 多层嵌套
class CityDevelop(BaseModel):
city:City
money:int = 666
campony:int = 888
class CityDevelopTarget(BaseModel):
citydevelop:CityDevelop
metro:int = 20
gdp:int = 50000
@app03.post("/stu03/multiple_param")
def stu03_multiple_param(
citydeveloptarget:CityDevelopTarget
):
return citydeveloptarget
# 纯列表请求体
@app03.post("/stu03/bodylist")
def stu03_body_list(
ListCity:List[City],
ListCityDevelop:List[CityDevelop]
):
return ListCity,ListCityDevelop
评论区