使用非关键字参数初始化FastApi basemodel(aka *args)

发布于 2025-01-29 18:47:40 字数 382 浏览 1 评论 0原文

我有一个fastapi我试图使用python元组初始化的项目,

from pydantic import BaseModel

class Item(BaseModel):
     name: str = ""
     surname: str = ""

data = ("jhon", "dhon")
Item(*data)

输出以下错误

TypeError: __init__() takes 1 positional argument but 3 were given

是否可以从一个初始化basemodel元组?

I have a FastApi item that I am trying to initialize using python tuples,

from pydantic import BaseModel

class Item(BaseModel):
     name: str = ""
     surname: str = ""

data = ("jhon", "dhon")
Item(*data)

Output the following error

TypeError: __init__() takes 1 positional argument but 3 were given

Is there a way to initialize a BaseModel from a tuple ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

东北女汉子 2025-02-05 18:47:40

不,Pydantic模型只能使用关键字参数初始化。如果您绝对必须从位置args初始化它,则可以查看该模式:

>>> Item(**dict(zip(Item.schema()["properties"], data)))
Item(name='jhon', surname='dhon')

No, Pydantic models can only be initialized with keyword arguments. If you absolutely must initialize it from positional args, you can look at the schema:

>>> Item(**dict(zip(Item.schema()["properties"], data)))
Item(name='jhon', surname='dhon')
她说她爱他 2025-02-05 18:47:40

我写了一个辅助功能,可以从元组加载数据,但是

def fill_model(model: BaseModel, columns: List, row: Tuple) -> BaseModel:

    base_model = model()
    model_keys = base_model.dict().keys()
    fields_count = len(model_keys)

    if fields_count != len(columns):
        raise ValueError("Columns length doesn't match fields count")

    if not set(columns).issubset(model_keys):
        raise ValueError("Columns doesn't match model fields")

    if fields_count != len(row):
        raise ValueError("Data length doesn't match fields count")

    return model(**{k: v for k, v in zip(columns, row)})

I wrote a helper function that can load data from the tuple but

def fill_model(model: BaseModel, columns: List, row: Tuple) -> BaseModel:

    base_model = model()
    model_keys = base_model.dict().keys()
    fields_count = len(model_keys)

    if fields_count != len(columns):
        raise ValueError("Columns length doesn't match fields count")

    if not set(columns).issubset(model_keys):
        raise ValueError("Columns doesn't match model fields")

    if fields_count != len(row):
        raise ValueError("Data length doesn't match fields count")

    return model(**{k: v for k, v in zip(columns, row)})
岁月苍老的讽刺 2025-02-05 18:47:40

您也可以使用pydantics baseModel parse_obj函数:item.parse_obj(some_dict)。
但是,您需要编写包装功能/使用类中的键。

from pydantic import BaseModel

class Item(BaseModel):
     name: str = ""
     surname: str = ""    
data = ("jhon", "dhon")
fields = Item.__fields__.keys()
zipped_dict = dict(zip(fields, data))
item = Item.parse_obj(zipped_dict)

鉴于您的元素始终包含正确的数据,因此在项目类中拥有更多条目非常容易处理,因此很容易处理这一点。

该解决方案将项目类的属性带有数据元组中的条目。将其转换为dict,可以使用pydantics parse_obj函数。

You can also use pydantics BaseModel parse_obj functions: Item.parse_obj(some_dict).
However, you would need to write a wrapper function/ use the keys from the class.

from pydantic import BaseModel

class Item(BaseModel):
     name: str = ""
     surname: str = ""    
data = ("jhon", "dhon")
fields = Item.__fields__.keys()
zipped_dict = dict(zip(fields, data))
item = Item.parse_obj(zipped_dict)

The nice part about this is, given that your tuples always contain the right data, having more entries in the Item class is pretty easy to handle.

This solution zips the properties of the Item class with the entries in the data tuple. Converting this to a dict, pydantics parse_obj function can be used.

错爱 2025-02-05 18:47:40

一个选项是仅覆盖__ Init __,设置位置参数并将其作为关键字参数传递给baseModel's Init:

from pydantic import BaseModel

class Item(BaseModel):
    name: str = ""
    surname: str = ""

    def __init__(self, name, surname):
        super().__init__(name=name, surname=surname)

data = ("jhon", "dhon")
Item(*data)

outputs: outputs:

Item(name='jhon', surname='dhon')

如果您有更多字段并希望有这种方法的更动态的版本,我在一个类似问题的答案中添加了更多示例: https://stackover.com/a /72657947/13696660

One option is just to override the __init__, set the positional arguments and pass them as keyword arguments to the BaseModel's init:

from pydantic import BaseModel

class Item(BaseModel):
    name: str = ""
    surname: str = ""

    def __init__(self, name, surname):
        super().__init__(name=name, surname=surname)

data = ("jhon", "dhon")
Item(*data)

Outputs:

Item(name='jhon', surname='dhon')

If you have more fields and wish to have a more dynamic version of this approach, I added more examples to an answer for a similar question: https://stackoverflow.com/a/72657947/13696660

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文