FastAPI开发文档教程-请求体-多个参数

admin 2026-01-10 10:51:23 编程 来源:ZONE.CI 全球网 0 阅读模式
  • 混合使用 Path、Query 和请求体参数
  • 多个请求体参数
  • 请求体中的单一值
  • 多个请求体参数和查询参数
  • 嵌入单个请求体参数
  • 总结

    既然我们已经知道了如何使用 Path 和 Query,下面让我们来了解一下请求体声明的更高级用法。

    混合使用 Path、Query 和请求体参数

    首先,毫无疑问地,你可以随意地混合使用 Path、Query 和请求体参数声明,FastAPI 会知道该如何处理。

    你还可以通过将默认值设置为 None 来将请求体参数声明为可选参数:

    Python 3.10+ Python 3.9+ Python 3.8+ Python 3.10+ non-Annotated Python 3.8+ non-Annotated

    1. from typing import Annotated
    2. from fastapi import FastAPI, Path
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: str | None = None
    8. price: float
    9. tax: float | None = None
    10. @app.put("/items/{item_id}")
    11. async def update_item(
    12. item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)], q: str | None = None, item: Item | None = None, ):
    13. results = {"item_id": item_id}
    14. if q:
    15. results.update({"q": q})
    16. if item:
    17. results.update({"item": item})
    18. return results`
    1. from typing import Annotated, Union
    2. from fastapi import FastAPI, Path
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: Union[str, None] = None
    8. price: float
    9. tax: Union[float, None] = None
    10. @app.put("/items/{item_id}")
    11. async def update_item(
    12. item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)], q: Union[str, None] = None, item: Union[Item, None] = None, ):
    13. results = {"item_id": item_id}
    14. if q:
    15. results.update({"q": q})
    16. if item:
    17. results.update({"item": item})
    18. return results`
    1. from typing import Union
    2. from fastapi import FastAPI, Path
    3. from pydantic import BaseModel
    4. from typing_extensions import Annotated
    5. app = FastAPI()
    6. class Item(BaseModel):
    7. name: str
    8. description: Union[str, None] = None
    9. price: float
    10. tax: Union[float, None] = None
    11. @app.put("/items/{item_id}")
    12. async def update_item(
    13. item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)], q: Union[str, None] = None, item: Union[Item, None] = None, ):
    14. results = {"item_id": item_id}
    15. if q:
    16. results.update({"q": q})
    17. if item:
    18. results.update({"item": item})
    19. return results`

    Tip

    尽可能选择使用 Annotated 的版本。

    1. from fastapi import FastAPI, Path
    2. from pydantic import BaseModel
    3. app = FastAPI()
    4. class Item(BaseModel):
    5. name: str
    6. description: str | None = None
    7. price: float
    8. tax: float | None = None
    9. @app.put("/items/{item_id}")
    10. async def update_item(
    11. *,
    12. item_id: int = Path(title="The ID of the item to get", ge=0, le=1000), q: str | None = None, item: Item | None = None, ):
    13. results = {"item_id": item_id}
    14. if q:
    15. results.update({"q": q})
    16. if item:
    17. results.update({"item": item})
    18. return results`

    Tip

    尽可能选择使用 Annotated 的版本。

    1. from typing import Union
    2. from fastapi import FastAPI, Path
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: Union[str, None] = None
    8. price: float
    9. tax: Union[float, None] = None
    10. @app.put("/items/{item_id}")
    11. async def update_item(
    12. *,
    13. item_id: int = Path(title="The ID of the item to get", ge=0, le=1000), q: Union[str, None] = None, item: Union[Item, None] = None, ):
    14. results = {"item_id": item_id}
    15. if q:
    16. results.update({"q": q})
    17. if item:
    18. results.update({"item": item})
    19. return results`

    Note

    请注意,在这种情况下,将从请求体获取的 item 是可选的。因为它的默认值为 None。

    多个请求体参数

    在上面的示例中,路径操作将期望一个具有 Item 的属性的 JSON 请求体,就像:

    { "name": "Foo", "description": "The pretender", "price": 42.0, "tax": 3.2 }

    但是你也可以声明多个请求体参数,例如 item 和 user:

    Python 3.10+Python 3.8+

    1. from fastapi import FastAPI
    2. from pydantic import BaseModel
    3. app = FastAPI()
    4. class Item(BaseModel):
    5. name: str
    6. description: str | None = None
    7. price: float
    8. tax: float | None = None
    9. class User(BaseModel):
    10. username: str
    11. full_name: str | None = None
    12. @app.put("/items/{item_id}")
    13. async def update_item(item_id: int, item: Item, user: User):
    14. results = {"item_id": item_id, "item": item, "user": user}
    15. return results`
    1. from typing import Union
    2. from fastapi import FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: Union[str, None] = None
    8. price: float
    9. tax: Union[float, None] = None
    10. class User(BaseModel):
    11. username: str
    12. full_name: Union[str, None] = None
    13. @app.put("/items/{item_id}")
    14. async def update_item(item_id: int, item: Item, user: User):
    15. results = {"item_id": item_id, "item": item, "user": user}
    16. return results`

    在这种情况下,FastAPI 将注意到该函数中有多个请求体参数(两个 Pydantic 模型参数)。

    因此,它将使用参数名称作为请求体中的键(字段名称),并期望一个类似于以下内容的请求体:

    { "item": { "name": "Foo", "description": "The pretender", "price": 42.0, "tax": 3.2 }, "user": { "username": "dave", "full_name": "Dave Grohl" } }

    Note

    请注意,即使 item 的声明方式与之前相同,但现在它被期望通过 item 键内嵌在请求体中。

    FastAPI 将自动对请求中的数据进行转换,因此 item 参数将接收指定的内容,user 参数也是如此。

    它将执行对复合数据的校验,并且像现在这样为 OpenAPI 模式和自动化文档对其进行记录。

    请求体中的单一值

    与使用 Query 和 Path 为查询参数和路径参数定义额外数据的方式相同,FastAPI 提供了一个同等的 Body。

    例如,为了扩展先前的模型,你可能决定除了 item 和 user 之外,还想在同一请求体中具有另一个键 importance。

    如果你就按原样声明它,因为它是一个单一值,FastAPI 将假定它是一个查询参数。

    但是你可以使用 Body 指示 FastAPI 将其作为请求体的另一个键进行处理。

    Python 3.10+Python 3.9+Python 3.8+Python 3.10+ non-AnnotatedPython 3.8+ non-Annotated

    1. from typing import Annotated
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: str | None = None
    8. price: float
    9. tax: float | None = None
    10. class User(BaseModel):
    11. username: str
    12. full_name: str | None = None
    13. @app.put("/items/{item_id}")
    14. async def update_item(
    15. item_id: int, item: Item, user: User, importance: Annotated[int, Body()] ):
    16. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    17. return results`
    1. from typing import Annotated, Union
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: Union[str, None] = None
    8. price: float
    9. tax: Union[float, None] = None
    10. class User(BaseModel):
    11. username: str
    12. full_name: Union[str, None] = None
    13. @app.put("/items/{item_id}")
    14. async def update_item(
    15. item_id: int, item: Item, user: User, importance: Annotated[int, Body()] ):
    16. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    17. return results`
    1. from typing import Union
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. from typing_extensions import Annotated
    5. app = FastAPI()
    6. class Item(BaseModel):
    7. name: str
    8. description: Union[str, None] = None
    9. price: float
    10. tax: Union[float, None] = None
    11. class User(BaseModel):
    12. username: str
    13. full_name: Union[str, None] = None
    14. @app.put("/items/{item_id}")
    15. async def update_item(
    16. item_id: int, item: Item, user: User, importance: Annotated[int, Body()] ):
    17. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    18. return results`

    Tip

    尽可能选择使用 Annotated 的版本。

    1. from fastapi import Body, FastAPI
    2. from pydantic import BaseModel
    3. app = FastAPI()
    4. class Item(BaseModel):
    5. name: str
    6. description: str | None = None
    7. price: float
    8. tax: float | None = None
    9. class User(BaseModel):
    10. username: str
    11. full_name: str | None = None
    12. @app.put("/items/{item_id}")
    13. async def update_item(item_id: int, item: Item, user: User, importance: int = Body()):
    14. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    15. return results`

    Tip

    尽可能选择使用 Annotated 的版本。

    1. from typing import Union
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: Union[str, None] = None
    8. price: float
    9. tax: Union[float, None] = None
    10. class User(BaseModel):
    11. username: str
    12. full_name: Union[str, None] = None
    13. @app.put("/items/{item_id}")
    14. async def update_item(item_id: int, item: Item, user: User, importance: int = Body()):
    15. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    16. return results`

    在这种情况下,FastAPI 将期望像这样的请求体:

    { "item": { "name": "Foo", "description": "The pretender", "price": 42.0, "tax": 3.2 }, "user": { "username": "dave", "full_name": "Dave Grohl" }, "importance": 5 }

    同样的,它将转换数据类型,校验,生成文档等。

    多个请求体参数和查询参数

    当然,除了请求体参数外,你还可以在任何需要的时候声明额外的查询参数。

    由于默认情况下单一值被解释为查询参数,因此你不必显式地添加 Query,你可以仅执行以下操作:

    q: str = None

    比如:

    Python 3.10+Python 3.9+Python 3.8+Python 3.10+ non-AnnotatedPython 3.8+ non-Annotated

    1. from typing import Annotated
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: str | None = None
    8. price: float
    9. tax: float | None = None
    10. class User(BaseModel):
    11. username: str
    12. full_name: str | None = None
    13. @app.put("/items/{item_id}")
    14. async def update_item(
    15. *,
    16. item_id: int,
    17. item: Item,
    18. user: User,
    19. importance: Annotated[int, Body(gt=0)], q: str | None = None,
    20. ):
    21. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    22. if q:
    23. results.update({"q": q})
    24. return results`
    1. from typing import Annotated, Union
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: Union[str, None] = None
    8. price: float
    9. tax: Union[float, None] = None
    10. class User(BaseModel):
    11. username: str
    12. full_name: Union[str, None] = None
    13. @app.put("/items/{item_id}")
    14. async def update_item(
    15. *,
    16. item_id: int,
    17. item: Item,
    18. user: User,
    19. importance: Annotated[int, Body(gt=0)], q: Union[str, None] = None,
    20. ):
    21. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    22. if q:
    23. results.update({"q": q})
    24. return results`
    1. from typing import Union
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. from typing_extensions import Annotated
    5. app = FastAPI()
    6. class Item(BaseModel):
    7. name: str
    8. description: Union[str, None] = None
    9. price: float
    10. tax: Union[float, None] = None
    11. class User(BaseModel):
    12. username: str
    13. full_name: Union[str, None] = None
    14. @app.put("/items/{item_id}")
    15. async def update_item(
    16. *,
    17. item_id: int,
    18. item: Item,
    19. user: User,
    20. importance: Annotated[int, Body(gt=0)], q: Union[str, None] = None,
    21. ):
    22. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    23. if q:
    24. results.update({"q": q})
    25. return results`

    Tip

    尽可能选择使用 Annotated 的版本。

    1. from fastapi import Body, FastAPI
    2. from pydantic import BaseModel
    3. app = FastAPI()
    4. class Item(BaseModel):
    5. name: str
    6. description: str | None = None
    7. price: float
    8. tax: float | None = None
    9. class User(BaseModel):
    10. username: str
    11. full_name: str | None = None
    12. @app.put("/items/{item_id}")
    13. async def update_item(
    14. *,
    15. item_id: int,
    16. item: Item,
    17. user: User,
    18. importance: int = Body(gt=0), q: str | None = None,
    19. ):
    20. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    21. if q:
    22. results.update({"q": q})
    23. return results`

    Tip

    尽可能选择使用 Annotated 的版本。

    1. from typing import Union
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: Union[str, None] = None
    8. price: float
    9. tax: Union[float, None] = None
    10. class User(BaseModel):
    11. username: str
    12. full_name: Union[str, None] = None
    13. @app.put("/items/{item_id}")
    14. async def update_item(
    15. *,
    16. item_id: int,
    17. item: Item,
    18. user: User,
    19. importance: int = Body(gt=0), q: Union[str, None] = None,
    20. ):
    21. results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    22. if q:
    23. results.update({"q": q})
    24. return results`

    Info

    Body 同样具有与 Query、Path 以及其他后面将看到的类完全相同的额外校验和元数据参数。

    嵌入单个请求体参数

    假设你只有一个来自 Pydantic 模型 Item 的请求体参数 item。

    默认情况下,FastAPI 将直接期望这样的请求体。

    但是,如果你希望它期望一个拥有 item 键并在值中包含模型内容的 JSON,就像在声明额外的请求体参数时所做的那样,则可以使用一个特殊的 Body 参数 embed:

    item: Item = Body(embed=True)

    比如:

    Python 3.10+Python 3.9+Python 3.8+Python 3.10+ non-AnnotatedPython 3.8+ non-Annotated

    1. from typing import Annotated
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: str | None = None
    8. price: float
    9. tax: float | None = None
    10. @app.put("/items/{item_id}")
    11. async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
    12. results = {"item_id": item_id, "item": item}
    13. return results`
    1. from typing import Annotated, Union
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: Union[str, None] = None
    8. price: float
    9. tax: Union[float, None] = None
    10. @app.put("/items/{item_id}")
    11. async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
    12. results = {"item_id": item_id, "item": item}
    13. return results`
    1. from typing import Union
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. from typing_extensions import Annotated
    5. app = FastAPI()
    6. class Item(BaseModel):
    7. name: str
    8. description: Union[str, None] = None
    9. price: float
    10. tax: Union[float, None] = None
    11. @app.put("/items/{item_id}")
    12. async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
    13. results = {"item_id": item_id, "item": item}
    14. return results`

    Tip

    尽可能选择使用 Annotated 的版本。

    1. from fastapi import Body, FastAPI
    2. from pydantic import BaseModel
    3. app = FastAPI()
    4. class Item(BaseModel):
    5. name: str
    6. description: str | None = None
    7. price: float
    8. tax: float | None = None
    9. @app.put("/items/{item_id}")
    10. async def update_item(item_id: int, item: Item = Body(embed=True)):
    11. results = {"item_id": item_id, "item": item}
    12. return results`

    Tip

    尽可能选择使用 Annotated 的版本。

    1. from typing import Union
    2. from fastapi import Body, FastAPI
    3. from pydantic import BaseModel
    4. app = FastAPI()
    5. class Item(BaseModel):
    6. name: str
    7. description: Union[str, None] = None
    8. price: float
    9. tax: Union[float, None] = None
    10. @app.put("/items/{item_id}")
    11. async def update_item(item_id: int, item: Item = Body(embed=True)):
    12. results = {"item_id": item_id, "item": item}
    13. return results`

    在这种情况下,FastAPI 将期望像这样的请求体:

    { "item": { "name": "Foo", "description": "The pretender", "price": 42.0, "tax": 3.2 } }

    而不是:

    { "name": "Foo", "description": "The pretender", "price": 42.0, "tax": 3.2 }

    总结

    你可以添加多个请求体参数到路径操作函数中,即使一个请求只能有一个请求体。

    但是 FastAPI 会处理它,在函数中为你提供正确的数据,并在路径操作中校验并记录正确的模式。

    你还可以声明将作为请求体的一部分所接收的单一值。

    你还可以指示 FastAPI 在仅声明了一个请求体参数的情况下,将原本的请求体嵌入到一个键中。

    FastAPI开发文档教程-请求体-多个参数 编程

    FastAPI开发文档教程-请求体-多个参数

    混合使用 Path、Query 和请求体参数多个请求体参数请求体中的单一值多个请求体参数和查询参数嵌入单个请求体参数总结既然我们已经知道了如何使用 Path 和 Query,下面让我们来了解一下请求体
    FastAPI开发文档教程-请求体 编程

    FastAPI开发文档教程-请求体

    导入 Pydantic 的 BaseModel创建数据模型声明请求体参数结论API 文档编辑器支持使用模型请求体 + 路径参数请求体 + 路径参数 + 查询参数不使用 PydanticFastAPI
    FastAPI开发文档教程-路径参数 编程

    FastAPI开发文档教程-路径参数

    声明路径参数的类型数据转换数据校验查看文档基于标准的好处,备选文档Pydantic顺序很重要预设值创建 Enum 类声明路径参数查看文档使用 Python 枚举类型比较枚举元素获取枚举值返回枚举元素包
    评论:0   参与:  0