前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FastAPI后台开发基础(10): 响应控制

FastAPI后台开发基础(10): 响应控制

原创
作者头像
bowenerchen
发布2024-10-23 16:38:48
1230
发布2024-10-23 16:38:48
举报
文章被收录于专栏:编码视界

定义预期的响应模型

代码语言:python
代码运行次数:0
复制
class ResponseModel(BaseModel):
    name: str = Field(..., description = 'user name',
                      alias = 'user_nick_name', # 赋值时使用这个别称
                      serialization_alias = 'user_name_in_json', # 序列化时使用这个别称
                      exclude = False)
    password: str = Field(..., description = 'user password',
                          exclude = True,  # JSON 序列化时不展示此字段
                          alias = 'user_password')
    id: str = Field(..., description = 'user id',
                    serialization_alias = 'unique_id')

使用response_model参数

代码语言:python
代码运行次数:0
复制
@app.post("/async", response_model = ResponseModel)
async def async_root():
    """
    使用 response_model 参数指定返回类型
    自动数据验证和序列化:FastAPI 会自动使用 ResponseModel 对返回的数据进行验证,并根据模型的配置(如 exclude 和 serialization_alias)序列化 JSON 响应
    文档自动生成:Swagger UI 和 Redoc 文档会自动显示正确的响应模型,包括字段描述和别名

    请求:curl -X 'POST' 'http://127.0.0.1:18081/async' -H 'accept: application/json' -d ''
    响应:{ "user_name_in_json": "demo-name", "unique_id": "demo-id" }
    """
    return ResponseModel(user_nick_name = 'demo-name',
                         user_password = '12345',
                         id = 'demo-id')
文档给出的响应示例
文档给出的响应示例

数据校验

代码语言:python
代码运行次数:0
复制
@app.post('/validate', response_model = ResponseModel)
async def validate_1():
    """
    数据验证
    当你在路由操作中指定了 response_model,FastAPI 会自动对返回的数据进行验证,确保它符合指定的 Pydantic 模型
    这意味着返回的数据必须能够被该模型接受,否则会抛出错误

    请求:curl -X 'POST' 'http://127.0.0.1:18081/validate' -H 'accept: application/json' -d ''
    响应:Internal Server Error
    后台报错:
    {'type': 'missing', 'loc': ('response', 'user_nick_name'), 'msg': 'Field required', 'input': {'a': 1, 'b': 2.0, 'c': 'hello,world'}}
    {'type': 'missing', 'loc': ('response', 'user_password'), 'msg': 'Field required', 'input': {'a': 1, 'b': 2.0, 'c': 'hello,world'}}
    {'type': 'missing', 'loc': ('response', 'id'), 'msg': 'Field required', 'input': {'a': 1, 'b': 2.0, 'c': 'hello,world'}}
    """
    return {'a': 1, 'b': 2.0, 'c': 'hello,world'}
响应数据校验错误
响应数据校验错误
后台报错
后台报错

字段序列化规则

代码语言:python
代码运行次数:0
复制
@app.post('/serialization',
          response_model = ResponseModel,
          response_model_by_alias = False,
          response_model_include = {'name', 'password'},
          response_model_exclude = {'id'})
async def serialization_1():
    """
    数据序列化
    使用模型字段的 alias(如果设置了 response_model_by_alias=True,这是默认行为)
    应用任何字段的 exclude 属性,从而在序列化时忽略某些字段
    应用 include 和 exclude 等参数(如果在 endpoint 函数中通过 response_model_include 或 response_model_exclude 显式指定)

    ResponseModel中已经显式指定要忽略 password
    response_model_exclude中显式指定要忽略 id
    最终实际返回只有 name 字段

    当同时使用这些参数和属性时,它们的作用是累加的

    具体的优先级如下:
    Pydantic 的 Field 属性 (include/exclude): 这些在模型级别定义,对所有操作都有基本的影响
    如果一个字段在模型中被设置为 exclude=True,那么无论路由级别的设置如何,这个字段都不会被包括在任何响应中

    FastAPI 的 response_model_include 和 response_model_exclude: 这些设置在路由级别,可以根据特定的 API 端点需求进一步细化响应
    它们会覆盖 Pydantic 模型中的设置,但只在特定的路由中有效

    请求:curl -X 'POST' 'http://127.0.0.1:18081/serialization' -H 'accept: application/json' -d ''
    响应:{"name":"demo-name"}
    """
    return ResponseModel(user_nick_name = 'demo-name',
                         user_password = '12345',
                         id = 'demo-id')
序列化后的响应
序列化后的响应

显式指定返回类型

代码语言:python
代码运行次数:0
复制
@app.post("/async2")
async def async_root2() -> ResponseModel:
    """
    显式指定返回类型
    文档生成:虽然 FastAPI 能够从类型注解中推断出响应模型,但在某些情况下,这种方式可能不如直接使用 response_model 参数那样直观清晰
    序列化控制较弱:不如 response_model 参数那样直接控制序列化过程中的细节(例如,排除某些字段)

    请求:curl -X 'POST' 'http://127.0.0.1:18081/async2' -H 'accept: application/json' -d ''
    响应:{ "user_name_in_json": "demo-name2", "unique_id": "demo-id2" }
    """
    return ResponseModel(user_nick_name = 'demo-name2',
                         user_password = '12345',
                         id = 'demo-id2')
显式指定响应类型
显式指定响应类型

response_model与显式指定响应类型的优先级

response_model与Response

代码语言:python
代码运行次数:0
复制
@app.post('/priority', response_model = ResponseModel)
async def priority_1() -> Response:
    """
    优先级处理
    如果在 endpoint 函数中同时使用了 response_model 和直接返回 Response 对象(如 JSONResponse)
    Response 对象将优先,这是因为 Response 对象被视为最终响应,FastAPI 不会对其内容进行进一步的处理或修改

    这种方法特别适用于以下场景:
    自定义响应:当你需要完全控制返回的 HTTP 响应的内容和格式时。
    性能敏感:当性能是一个关键考虑因素,且你希望避免额外的处理开销时。
    兼容性和遗留系统:当你需要与遗留系统或外部系统交互,这些系统期望特定格式的响应时。

    请求:curl -X 'POST' 'http://127.0.0.1:18081/priority' -H 'accept: application/json' -d ''
    响应:{ "a": 1, "b": 2, "c": "hello,world" }
    """
    return JSONResponse(content = {'a': 1, 'b': 2.0, 'c': 'hello,world'})
Response 优先级更高
Response 优先级更高

response_model与显式指定自定义返回类型

代码语言:python
代码运行次数:0
复制
class AnotherModel(BaseModel):
    test: str
    a: str
    b: str


@app.post('/priority2', response_model = ResponseModel)
async def priority_2() -> AnotherModel:
    """
    优先级处理
    如果在 endpoint 函数中同时使用了 response_model 和直接返回 Response 对象(如 JSONResponse)
    Response 对象将优先,这是因为 Response 对象被视为最终响应,FastAPI 不会对其内容进行进一步的处理或修改

    请求:curl -X 'POST' 'http://127.0.0.1:18081/priority2' -H 'accept: application/json' -d ''
    响应:Internal Server Error
    报错:
    {'type': 'missing', 'loc': ('response', 'user_nick_name'), 'msg': 'Field required', 'input': AnotherModel(test='test', a='a', b='b')}
    {'type': 'missing', 'loc': ('response', 'user_password'), 'msg': 'Field required', 'input': AnotherModel(test='test', a='a', b='b')}
    {'type': 'missing', 'loc': ('response', 'id'), 'msg': 'Field required', 'input': AnotherModel(test='test', a='a', b='b')}
    """
    return AnotherModel(test = 'test', a = 'a', b = 'b')
响应错误
响应错误
后台报错
后台报错

使用Response 泛型

代码语言:python
代码运行次数:0
复制
@app.get('/redirect')
async def redirect(redirect_to: Annotated[bool, Query()] = True) -> Response:
    """
    可能返回多种响应类型
    高度灵活:可以根据函数逻辑返回不同类型的响应,如重定向或 JSON 响应
    明确控制:直接控制响应的具体类型和内容,适用于需要根据不同条件返回不同响应类型的场景
    文档生成:自动生成的 API 文档可能不如使用 response_model 那样清晰,因为返回类型是泛型的 Response

    请求:curl -X 'GET' 'http://127.0.0.1:18081/redirect?redirect_to=false' -H 'accept: application/json'
    响应:{"message":"no redirect needed"}
    """
    if redirect_to:
        return RedirectResponse(url = 'https://www.qq.com')
    else:
        return JSONResponse(content = {'message': 'no redirect needed'})
重定向效果
重定向效果
JSON 响应
JSON 响应

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 定义预期的响应模型
  • 使用response_model参数
    • 数据校验
      • 字段序列化规则
      • 显式指定返回类型
      • response_model与显式指定响应类型的优先级
        • response_model与Response
          • response_model与显式指定自定义返回类型
          • 使用Response 泛型
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档