当前位置: 首页 > 知识库问答 >
问题:

FastAPI swagger不喜欢通过查询参数传递的字符串列表,但endpoint可以在浏览器中工作

董琦
2023-03-14

FastAPI中的RESTAPIendpoint通过单个查询参数接受字符串列表,我遇到了一个问题。此endpoint的用法示例如下:

http://127.0.0.1:8000/items/2?short=false&response=this&response=that

在这里,名为“响应”的参数接受FastAPI教程中关于查询参数和字符串验证的部分中记录的字符串列表。endpoint在浏览器中按预期工作。

但是,它在Swagger文档中不起作用。单击“执行”以测试endpoint时,标记为“添加字符串项”的按钮会摇晃。Swagger UI似乎无法使用嵌入的查询参数创建预期的URL(如图1所示)。

endpoint的代码如下。我试过,有没有验证。

@app.get("/items/{item_ID}")
async def getQuestion_byID(item_ID: int = Path(
                    ...,
                    title = "Numeric ID of the question",
                    description = "Specify a number between 1 and 999",
                    ge = 1,
                    le = 999
                ), response: Optional[List[str]] = Query(
                    [],
                    title="Furnish an answer",
                    description="Answer can only have letters of the alphabet and is case-insensitive",
                    min_length=3,
                    max_length=99,
                    regex="^[a-zA-Z]+$"
                ), short: bool = Query(
                    False,
                    title="Set flag for short result",
                    description="Acceptable values are 1, True, true, on, yes"
                )):
    """
    Returns the quiz question or the result.
    Accepts item ID as path parameter and
    optionally response as query parameter.
    Returns result when the response is passed with the item ID. 
    Otherwise, returns the quiz question.
    """
    item = question_bank.get(item_ID, None)
    if not item:
        return {"question": None}
    if response:
        return evaluate_response(item_ID, response, short)
    else:
        return {"question": item["question"]}

感谢任何帮助。

共有1个答案

颛孙高义
2023-03-14

如这里所述,这是由于OpenAPI将模式(以及最小最大约束)应用于数组本身的架构,而不仅仅是数组中的单个。如果您在http://127.0.0.1:8000/openapi.json检查OpenAPI架构,您会看到响应参数的架构如下所示(即,验证也应用于数组本身):

      {
        "description": "Answer can only have letters of the alphabet and is case-insensitive",
        "required": false,
        "schema": {
          "title": "Furnish an answer",
          "maxLength": 99,
          "minLength": 3,
          "pattern": "^[a-zA-Z]+$",
          "type": "array",
          "items": {
            "maxLength": 99,
            "minLength": 3,
            "pattern": "^[a-zA-Z]+$",
            "type": "string"
          },
          "description": "Answer can only have letters of the alphabet and is case-insensitive",
          "default": []
        },
        "name": "response",
        "in": "query"
      }

正如这里提到的,您可以使用Pyd的配置来指定项目与该限制:

my_constr = constr(regex="^[a-zA-Z]+$", min_length=3, max_length=99)
response: Optional[List[my_constr]] = Query([], title="Furnish an...", description="Answer can...")

保持您的响应参数不变http://127.0.0.1:8000/openapi.json,从response数组)模式中删除模式>(以及最小最大

    ...
    {
    "description": "Answer can only have letters of the alphabet and is case-insensitive",
    "required": false,
    "schema": {
      "title": "Furnish an answer",
      "type": "array",
      "items": {
        "maxLength": 99,
        "minLength": 3,
        "pattern": "^[a-zA-Z]+$",
        "type": "string"
      },
      "description": "Answer can only have letters of the alphabet and is case-insensitive",
      "default": []
    },
    "name": "response",
    "in": "query"
    },
    ...

然后,在应用程序中,指示FastAPI使用该模式:

import json
app.openapi_schema = json.load(open("my_openapi.json"))

由于上述解决方案要求您在每次进行更改或添加新endpoint/参数时复制和编辑架构,因此您宁愿按照此处所述修改OpenAPI架构。这将使您免于复制/编辑架构文件。请确保在代码末尾添加以下内容(在定义所有路由之后)。

from fastapi.openapi.utils import get_openapi

def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema
    openapi_schema = get_openapi(
        title="FastAPI",
        version="0.1.0",
        description="This is a very custom OpenAPI schema",
        routes=app.routes,
    )
    del openapi_schema["paths"]["/items/{item_ID}"]["get"]["parameters"][1]["schema"]["maxLength"]
    del openapi_schema["paths"]["/items/{item_ID}"]["get"]["parameters"][1]["schema"]["minLength"]
    del openapi_schema["paths"]["/items/{item_ID}"]["get"]["parameters"][1]["schema"]["pattern"]
    
    app.openapi_schema = openapi_schema
    return app.openapi_schema
    
    
app.openapi = custom_openapi

在上述所有解决方案中,通常显示在OpenAPI中< code>response下的约束注释(即< code >(query)maxlength:99 minlength:3 pattern:^[a-za-z]$ )不会出现(因为Swagger会从应用于< code>array而不是< code>items的约束中创建该注释),但似乎没有办法保留这一点。然而,在解决方案2和3中,您可以修改上面的< code>JSON代码片段中所示的< code >“in”属性,以手动添加注释。但是,作为< code>HTML元素,等等。,由Swagger控制,整个注释将出现在括号内,约束之间没有换行符。尽管如此,您仍然可以通过在< code>Query参数的< code>description中指定应用于< code>items的约束来通知用户。

 类似资料:
  • 问题内容: 在C#中使用SqlCommand,我创建了一个查询,其中在where子句中包含IN(列表…)部分。我不需要遍历我的字符串列表来生成列表,而是需要查询(如果您在sqlInjection中考虑,则很危险)。我以为我可以创建一个像这样的参数: 然后在代码中,我尝试添加一个像这样的参数: 但这是行不通的。 问题: 我在尝试一些不可能的事情吗? 我采取了错误的方法吗? 我在这种方法上有错误吗?

  • 我需要传递一个字符串参数作为querystring参数,这应该是可选的。 在这里,我希望将位置作为可选参数。我试着用作为。但它对我不起作用。让我知道解决方案。

  • 问题内容: UIView需要根据自定义控件的完成处理程序更改警告标签: 最后的动画块显示表格中的错误。 如果我在完成闭包之外的某个地方调用它,那么它将起作用。 问题答案: 问题是闭包隐式返回此表达式的结果: 但闭包本身被声明为returning 。 添加一个显式应该可以解决此问题:

  • 问题内容: 是否存在通过查询字符串传递数组的标准方法? 需要明确的是,我有一个带有多个值的查询字符串,其中一个是数组值。我希望将该查询字符串值视为一个数组-我不希望该数组爆炸,以使其与其他查询字符串变量没有区别。 编辑: 根据@Alex的答案,没有标准的方法可以执行此操作,因此我的后续工作是什么才是 识别 我正在读取的参数同时是 PHP 和 Javascript 数组的简单方法? 用相同的名称命名

  • 我试图做一个文件上传到一个链接(共享点Rest服务),在chrome浏览器中工作良好,但不是在android WebView。 我知道android webview有很多限制,但我尝试使用以下方法上传一个文件 https://github.com/mgks/os-fileup 它打开浏览器,但它不显示文件名,也不上传任何内容或调用服务,但同样的代码在chrome浏览器中运行良好(请注意,我已经启用

  • 问题内容: 我喜欢使用URL之类的,而不是传递URL之类的查询字符串。 如何在Struts2中做到这一点? 我做了如下。但它不起作用,显示500错误代码 问题答案: 在2.1+下使用纯Struts2是不可能的。解决方法是,可以使用UrlRewriterfilter进行此操作。从Struts2的2.1+使用通配符的帮助下,你可以使用像看到这样的帖子,但不喜欢。区别在于在第二种情况下没有参数名称。解决