首页 > 编程问答 >如何在 Litestar GET 路由中使用 Pydantic 模型作为查询参数

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

时间:2024-07-27 05:52:04浏览次数:14  
标签:python query-string pydantic litestar

我正在尝试使用 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"
        }
    ]
}
    "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 模型作为查询参数?我在序列化过程中缺少什么?有可能吗?

附加上下文:

  • Litestar 版本:2.10.0
  • Pydantic 版本:2.8.2
  • httpx 版本:0.27.0

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


遇到的问题是 Litestar 预计查询参数将作为字符串传递。默认情况下,它不会自动将 JSON 字符串解析为 Pydantic 模型。

可以通过以下两种方式解决此问题:

1. 使用 Query 参数和 config=

可以使用 Query 参数明确地从查询字符串中提取数据,并使用 config= 来指定如何解析数据。在这种情况下,我们可以使用 Depends 来调用 Pydantic 模型的 .parse_obj 方法。

from pydantic import BaseModel
from litestar import Litestar, get, Controller
from litestar.params import Query
from typing import Depends

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

class RootController(Controller):
    path = "/"

    @get()
    def input(self, input: Input = Depends(Input.parse_obj, config=Query(alias="input"))) -> str:
        return input.foo + input.bar


app = Litestar(route_handlers=[RootController])

在这个例子中, Query(alias="input") 将告诉 Litestar 从名为 "input" 的查询参数中获取值。然后, Depends(Input.parse_obj, ...) 将使用 Input.parse_obj 方法解析该值。

2. 将查询参数作为单独的参数传递

可以将 foo bar 作为单独的查询参数传递,然后让 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

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

这将使 Litestar 自动将 foo bar 查询参数解析到 Input 模型中。

选择哪种方法?

  • 如果的查询参数结构复杂且希望将 JSON 字符串直接传递给 API,则第一个方法(使用 Query Depends )更适合。
  • 如果的查询参数相对简单,则第二个方法(将查询参数作为单独的参数传递)更简洁易懂。

希望这些解决方案可以帮助解决问题!

标签:python,query-string,pydantic,litestar
From: 78799973

相关文章

  • Python griddata() 和 Matlab griddata():某些网格点的结果不同
    在将一些(相当大的物理)Matlab代码转换为Python时,我偶然发现了这种情况。当对相同的二维离散数据进行插值时,Python/Scipy的griddata()函数给出的结果与Matlab的对应函数不同。griddata()Matlab示例代码:Python示例代码:%Samplepoints(x,y):7x5=3......
  • Ebay Python SDK 仅在特定项目类别上返回错误
    我在一个项目中使用ebaySDK一段时间了。最近我尝试导入一些商品,例如手表、手机壳等...并且我使用了eBay自己通过eBay返回的英国商店页面上的类别ID他们的“get_category_suggestions”API端点,但eBay似乎有选择地决定拒绝某些项目并引发服务器错误!为了测试,我做了......
  • 使用特定的Python版本(MacOS)制作virtualenv
    我安装了brew,python3(默认和最新版本)和pip3,pyenv。TensorFlow现在不支持python3.7,所以我听说我应该制作一个独立运行3.6或更低版本的virtualenv。我安装了python3.6.7bypyenvinstall3.6.7但无法制作virtualenv-p3.6.7(mydir)因为3.6.7不在P......
  • 使用Python去除图像中的线条
    我正在尝试使用Python和cv2、numpy、skimage等从黑白图像中删除“阴影线”(如果图像中存在“阴影线”)。本质上,我的图像可以有1或2条曲线,如下例所示。但每条线都有一条1-5像素外的阴影线,需要删除。我怎样才能在Python中做到这一点?原始......
  • Python 和 OpenCV:如何裁剪半成形边界框
    我有一个为无网格表创建网格线的脚本:脚本之前:脚本之后:是否有一种简单的方法,使用OpenCV来裁剪“脚本之后”图像,使其仅包含四边边界框?示例输出:编辑:我目前正在研究一种解决方案,该解决方案可以找到垂直/水平方向的第一条/最后一条......
  • 使用类型提示将 Python 转换为 Cython
    类型提示现在在Python3.5版本中可用。在规范(PEP484)中,目标(和非目标)被明确暴露:#RationaleandGoals此PEP旨在为类型注释提供标准语法,开放Python代码更容易静态分析和重构、潜在的运行时类型检查以及(也许在某些情况下)利用类型信息生成代码。......
  • 在 Python 类型提示中区分 PySpark 和 Pandas DataFrame (PyCharm)
    在PyCharm中,如果使用apyspark.sql.DataFrame代替pandas.DataFrame,类型提示似乎不会触发警告,反之亦然。例如以下代码根本不会生成任何警告:frompyspark.sqlimportDataFrameasSparkDataFramefrompandasimportDataFrameasPandasDataFramedef......
  • 如何在Python中继承类型提示?
    所以我的问题是,当我有一个A类型的类来做事情并且我使用这些函数作为subclass(B)时,它们仍然是类A的类型,并且不接受我的类B对象作为参数或作为函数签名。我的问题简化了:fromtypingimportTypeVar,Generic,CallableT=TypeVar('T'......
  • Python - 如何传递类对象的函数参数类型(打字)
    我想python3.7附带了(不确定),不仅可以将变量名传递给函数,还可以传递变量的类型。我想知道的是是否有可能传递特定类的类型。以同样的方式传递:deffoo_func(i:int)->None:pass如果我有一个类,让我们说:classfoo_class(object):pass我如何转换fo......
  • 使用 Python 构建简单 REST API
    使用Python构建简单RESTAPI1.概述本技术文档旨在指导开发者使用Python框架Flask构建一个基本的RESTAPI。通过学习本指南,您将掌握创建、读取、更新和删除(CRUD)操作的基本知识,并能够使用Python构建自己的API。2.安装依赖首先,您需要确保已安装Python和Flask......