前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FastAPI后台开发基础(4):FastAPI 官网文档错误、编码错误以及注意要点记录

FastAPI后台开发基础(4):FastAPI 官网文档错误、编码错误以及注意要点记录

原创
作者头像
bowenerchen
发布2024-10-10 21:54:53
2443
发布2024-10-10 21:54:53
举报
文章被收录于专栏:编码视界

设置查询参数是否为必填

使用Annotated装饰查询参数

不设置default值

代码语言:python
代码运行次数:0
复制
@app.get("/validation")
async def async_root(str_param: Annotated[str | None, Query(min_length = 3,
                                                            max_length = 20,
                                                            pattern = '^[a-zA-Z0-9]+$',
                                                            description = 'This is a string parameter')]):
    """
    如果不设置 str_param = None, 则 str_param 为必填
    """
    ret = {"str_list": str_param}
    if str_param is not None:
        h = hashlib.sha3_512(str_param.encode('utf-8')).hexdigest()
        ret.update({"sha3_512": h})
    else:
        ret.update({"uuid": uuid.uuid4().hex})
    return ret
不设置默认值
不设置默认值
生成的文档中参数为必填
生成的文档中参数为必填

设置default值

代码语言:python
代码运行次数:0
复制
@app.get("/validation1")
async def async_root1(str_param: Annotated[str | None, Query(min_length = 3,
                                                             max_length = 20,
                                                             pattern = '^[a-zA-Z0-9]+$',
                                                             description = 'This is a string parameter')] = None):
    """
    设置 str_param = None 表明允许 str_param 为空(非必填)
    """
    ret = {"str_list": str_param}
    if str_param is not None:
        h = hashlib.sha3_512(str_param.encode('utf-8')).hexdigest()
        ret.update({"sha3_512": h})
    else:
        ret.update({"uuid": uuid.uuid4().hex})
    return ret
设置 default 值
设置 default 值
生成的文档中参数为非必填
生成的文档中参数为非必填

string 类型的默认值

代码语言:python
代码运行次数:0
复制
@app.get("/validation2")
async def async_root2(str_param: Annotated[str, Query(min_length = 3,
                                                      max_length = 20,
                                                      pattern = '^[a-zA-Z0-9]+$',
                                                      description = 'This is a string parameter')] = 'default_value'):
    """
    此时 str_list 有默认值,非必填
    """
    ret = {"str_list": str_param}
    if str_param is not None:
        h = hashlib.sha3_512(str_param.encode('utf-8')).hexdigest()
        ret.update({"sha3_512": h})
    else:
        ret.update({"uuid": uuid.uuid4().hex})
    return ret
默认值为 string 类型
默认值为 string 类型

使用ellipsis作为默认值

错误写法
代码语言:python
代码运行次数:0
复制
@app.get("/validation3")
async def async_root3(str_param: Annotated[str, Query(min_length = 3,
                                                      max_length = 20,
                                                      pattern = '^[a-zA-Z0-9]+$',
                                                      description = 'This is a string parameter')] = ...):
    """
    此时 str_list = ... 生成的文档中,str_list 并非为必填
    并且当发送请求:
        curl -X 'GET' 'http://127.0.0.1:18081/validation3' -H 'accept: application/json'
    后台会报错:
        ValueError: [TypeError("'ellipsis' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]
    """
    ret = {}
    if str_param is not ...:
        ret = {"str_list": str_param}
        h = hashlib.sha3_512(str_param.encode('utf-8')).hexdigest()
        ret.update({"sha3_512": h})
    else:
        ret.update({"uuid": uuid.uuid4().hex, 'error': 'str_list is ...'})
    return ret


@app.get("/validation4")
async def async_root4(str_param: Annotated[str | None, Query(min_length = 3,
                                                             max_length = 20,
                                                             pattern = '^[a-zA-Z0-9]+$',
                                                             description = 'This is a string parameter')] = ...):
    """
    发送:curl -X 'GET' 'http://127.0.0.1:18081/validation4' -H 'accept: application/json'时
    后台会报错:ValueError: [TypeError("'ellipsis' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]
    """
    ret = {}
    if str_param is not ...:
        ret = {"str_list": str_param}
        h = hashlib.sha3_512(str_param.encode('utf-8')).hexdigest()
        ret.update({"sha3_512": h})
    else:
        ret.update({"uuid": uuid.uuid4().hex, 'error': 'str_list is ...'})
    return ret

使用 Query(xxxx) = ...的写法均会引起错误,此种写法来源于 FastAPI 官网的文档:

使用ellipsis设置必填参数

错误的文档示例
错误的文档示例

关于此错误写法笔者已经给 FastAPI 提了 Issue:https://github.com/fastapi/fastapi/issues/12313

相关开发者回复
相关开发者回复
正确写法
代码语言:python
代码运行次数:0
复制
@app.get("/validation5")
async def async_root5(str_param: Annotated[str, Query(default = ...,
                                                      min_length = 3,
                                                      max_length = 20,
                                                      pattern = '^[a-zA-Z0-9]+$',
                                                      description = 'This is a string parameter')]):
    """
    使用 Query(default = ...) 的方式设置 str_list 为必填参数
    不使用 default 时参数也会默认为必填
    Remember that in most of the cases, when something is required,
    you can simply omit the default, so you normally don't have to use ...
    """
    ret = {"str_list": str_param}
    h = hashlib.sha3_512(str_param.encode('utf-8')).hexdigest()
    ret.update({"sha3_512": h})
    ret.update({"uuid": uuid.uuid4().hex})
    return ret
使用ellipsis作为默认值来设定必填属性
使用ellipsis作为默认值来设定必填属性

官网文档中关于必填参数可以为None的错误描述

官网文档描述链接

如果一个参数为必填同时还可以为 None 的错误描述
如果一个参数为必填同时还可以为 None 的错误描述

关于这个问题也提了 Issue 给到 FastAPI 团队:Question about "Required, can be None"

问题得到了 FastAPI 开发者的确认
问题得到了 FastAPI 开发者的确认

关于这个问题的讨论帖:Discussion,感兴趣的可以自行查看。

Annotated搭配 Query(default=xxxx)带来的问题

代码语言:python
代码运行次数:0
复制
@app.get("/validation1_1")
async def async_root1_1(str_param: Annotated[str | None, Query(default = 'test',
                                                               min_length = 3,
                                                               max_length = 20,
                                                               pattern = '^[a-zA-Z0-9]+$',
                                                               description = 'This is a string parameter')]):
    ret = {"str_list": str_param}
    if str_param is not None:
        h = hashlib.sha3_512(str_param.encode('utf-8')).hexdigest()
        ret.update({"sha3_512": h})
    else:
        ret.update({"uuid": uuid.uuid4().hex})
    return ret
使用  Query 的 default 参数设置默认值
使用 Query 的 default 参数设置默认值

运行时会报错:

代码语言:shell
复制
AssertionError: `Query` default value cannot be set in `Annotated` for 'str_param'. Set the default value with `=` instead.
Amazon Q AI 给出的答复
Amazon Q AI 给出的答复

总之在使用Annotated搭配 Query 时需要注意编码细节。

列表查询参数

代码语言:python
代码运行次数:0
复制
@app.get("/validation7")
async def async_root7(str_list: Annotated[List[str] | None, Query(min_length = 1)]):
    """
    列表查询参数
    curl -X 'GET' 'http://127.0.0.1:18081/validation7?str_list=aaa&str_list=bbb&str_list=ccc' -H 'accept: application/json'
    """
    if str_list is not None:
        return {'items_count': len(str_list), 'items': str_list}
    else:
        return {'message': 'no items'}
运行效果
运行效果

路径参数使用alias别名的注意点

代码语言:python
代码运行次数:0
复制
@app.get('/{item_id}')
async def async_root(item_id: Annotated[int, Path(title = 'Item ID', alias = 'xid')]):
    """
    GithubIssue: https://github.com/fastapi/fastapi/issues/12323
    当带有 alias 时,接口无法正常工作:
        curl http://127.0.0.1:18081/123
        {"detail":[{"type":"missing","loc":["path","xid"],"msg":"Field required","input":null}]}
    """
    return {'item_id': item_id}

@app.get('/{xid_2}')
async def async_root2(item_id: Annotated[int, Path(title = 'Item ID', alias = 'xid_2')]):
    """
    The title parameter you're referring to in the Path function is part of FastAPI's path parameter customization. While it doesn't directly appear in the Swagger UI documentation, it serves an important purpose in the OpenAPI schema.
    Here's what the title parameter does:
        OpenAPI Schema: The title is included in the OpenAPI (formerly Swagger) schema that FastAPI generates.
                        This schema is a machine-readable description of your API, which can be used by various tools and clients.
        JSON Schema: In the context of JSON Schema (which OpenAPI uses), the title provides a human-readable name for the parameter.
                     It's meant to be a brief description of the parameter.
        API Documentation: While not directly visible in the Swagger UI,
                           the title can be used by other documentation tools that consume the OpenAPI schema to provide more descriptive names for parameters.
        Code Generation: Tools that generate client code from OpenAPI schemas might use the title to create more meaningful variable or property names.
    """
    return {'item_id': item_id}

相关 issue 讨论帖:Should the alias parameter in the Path method be removed?

相关回复
相关回复

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 设置查询参数是否为必填
    • 使用Annotated装饰查询参数
      • 不设置default值
      • 设置default值
      • string 类型的默认值
      • 使用ellipsis作为默认值
      • 官网文档中关于必填参数可以为None的错误描述
      • Annotated搭配 Query(default=xxxx)带来的问题
      • 列表查询参数
  • 路径参数使用alias别名的注意点
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档