如何在Litestar GET Route中使用Pydantic模型作为查询参数

问题描述 投票:0回答:1

我正在尝试使用 Litestar 创建一条 GET 路由,该路由利用 Pydantic 模型作为查询参数。但是,序列化并没有按预期工作。

这是重现我的问题的最小示例:

from pydantic import BaseModel
from litestar import Litestar, get, Controller


class Input(BaseModel):
    foo: str
    bar: str


class RootController(Controller):
    path = "/"

    @get()
    def input(self, input: Input) -> str:
        return input.foo + input.bar


app = Litestar(route_handlers=[RootController])

以及以下 GET 请求:

import httpx
import json

params = {
    "input": {
        "foo": "test",
        "bar": "this"
    }
}

def prepare_encode(params: dict) -> dict:
    for key, value in params.items():
        if isinstance(value, dict):
            params[key] = json.dumps(value, indent=None)
    return params

params = prepare_encode(params)
response = httpx.get("http://localhost:8000/", params=params)
response.json()

GET 请求导致以下错误:

{
    "status_code": 400,
    "detail": "Validation failed for GET /?input=%7B%22foo%22%3A%20%22test%22%2C%20%22bar%22%3A%20%22this%22%7D",
    "extra": [
        {
            "message": "Input should be a valid dictionary or instance of Input"
        }
    ]
}

查询参数似乎没有正确序列化到

Input
Pydantic 模型中。

我尝试过的:

  • 使用
    json.dumps
    对字典进行编码,然后将其作为参数发送。
  • 调试 Litestar 模型实现,其中查询参数作为字符串提供到 msgspec 转换中。这显然不符合所需的类型。

预期行为: 我希望

input
查询参数能够正确解析并序列化到
Input
模型中,从而允许 GET 请求成功而不会出现验证错误。

问题: 如何在 Litestar GET 路由中正确传递 Pydantic 模型作为查询参数?我在序列化过程中缺少什么?有可能吗?

其他背景:

  • 莱特星版本:2.10.0
  • Pydantic 版本:2.8.2
  • httpx版本:0.27.0

任何帮助或指导将不胜感激。

python query-string pydantic litestar
1个回答
0
投票

实际上,你的请求方式和处理方式都存在问题。首先,我无法在 docs 中找到使用

Pydantic
模型作为查询参数的可能性 FastAPI 。不过你可以通过 DI 机制自己实现类似的逻辑:

def build_input(foo: str, bar: str) -> Input:
    """Prepare input model from query params."""""

    return Input(foo=foo, bar=bar)


class RootController(Controller):
    path = "/"

    @get(dependencies={"input": Provide(build_input)})
    def input(self, input: Input) -> str:
        return input.foo + input.bar

其次,如果您想使用嵌套结构作为输入,您最好使用

POST
方法。

{
    "input": {
        "foo": "test",
        "bar": "this"
    }
}

否则,上面的字典在用作查询时将被转换为以下字符串:

%7B%22foo%22%3A%20%22test%22%2C%20%22bar%22%3A%20%22this%22%7D

我假设您想做的是以下事情:

response = httpx.get(
    "http://localhost:8000/", 
    params={
        "foo": "test",
        "bar": "this"
    }
)

有了这些改变,一切似乎都正常了!

© www.soinside.com 2019 - 2024. All rights reserved.