如何使用 FastAPI 在查询参数名称中允许使用连字符 (-)?

Ami*_* Ba 3 python query-string pydantic fastapi

我有一个简单的应用程序如下:

from typing import Annotated

import uvicorn
from fastapi import FastAPI, Query, Depends
from pydantic import BaseModel

app = FastAPI()


class Input(BaseModel):
    a: Annotated[str, Query(..., alias="your_name")]


@app.get("/")
def test(inp: Annotated[Input, Depends()]):
    return f"Hello {inp.a}"


def main():
    uvicorn.run("run:app", host="0.0.0.0", reload=True, port=8001)


if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

curl "http://127.0.0.1:8001/?your_name=amin"返回“你好阿明”


我现在将别名从 更改your_nameyour-name

from typing import Annotated

import uvicorn
from fastapi import FastAPI, Query, Depends
from pydantic import BaseModel

app = FastAPI()


class Input(BaseModel):
    a: Annotated[str, Query(..., alias="your-name")]


@app.get("/")
def test(inp: Annotated[Input, Depends()]):
    return f"Hello {inp.a}"


def main():
    uvicorn.run("run:app", host="0.0.0.0", reload=True, port=8001)


if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

然后curl "http://127.0.0.1:8001/?your-name=amin"返回:

{"detail":[{"loc":["query","extra_data"],"msg":"field required","type":"value_error.missing"}]}
Run Code Online (Sandbox Code Playgroud)

但是,在更简单的应用程序中允许使用连字符别名。

{"detail":[{"loc":["query","extra_data"],"msg":"field required","type":"value_error.missing"}]}
Run Code Online (Sandbox Code Playgroud)

curl "http://127.0.0.1:8001/?your-name=amin"返回“你好阿明”



这是一个错误吗?这里有什么问题?

Chr*_*ris 5

问题概述

\n

正如 @JarroVGIT 所解释的这是来自 Pydantic 的行为,而不是 FastAPI。如果您仔细查看您发布的错误:

\n
{"detail":[{"loc":["query","extra_data"],"msg":"field required","type":"value_error.missing"}]}\n
Run Code Online (Sandbox Code Playgroud)\n

它讨论了名为 \xe2\x80\x94 的查询参数的缺失值extra_data,但是,您的BaseModel. 事实上,如果您在 处使用了 Swagger UI 自动文档/docs,您会看到您的端点需要一个名为 的必需参数extra_data。正如 @JarroVGIT 在上面的链接讨论中指出的:

\n
\n

每当您提供“非Pythonic”别名(如破折号/连字符)时,inspect.signature()从该子类获得的签名BaseModel将被分组在 kwargs 中extra_data

\n
\n

因此,出现有关查询参数缺失值的错误extra_data

\n

解决方案1

\n

您可以将 包裹Query()在 a 中,如本答案Field()所示。例子:

\n
from fastapi import Query, Depends\nfrom pydantic import BaseModel, Field\n\nclass Input(BaseModel):\n    a: str = Field(Query(..., alias="your-name"))\n\n\n@app.get("/")\ndef main(i: Input = Depends()):\n    pass\n
Run Code Online (Sandbox Code Playgroud)\n

解决方案2

\n

如这个答案这个答案所示,您可以使用单独的依赖项类,而不是BaseModel. 例子:

\n
from fastapi import Query, Depends\nfrom dataclasses import dataclass\n\n@dataclass\nclass Input:\n    a: str = Query(..., alias="your-name")\n\n\n@app.get("/")\ndef main(i: Input = Depends()):\n    pass\n
Run Code Online (Sandbox Code Playgroud)\n

解决方案3

\n

直接在端点中声明查询参数,而不是使用 Pydantic BaseModel。例子:

\n
from fastapi import Query\n\n@app.get("/")\ndef main(a: str = Query(..., alias="your-name")):\n    pass\n
Run Code Online (Sandbox Code Playgroud)\n