pydantic basemodel“ field”仅出于验证目的

发布于 2025-02-02 19:54:49 字数 620 浏览 3 评论 0原文

考虑说明使用pydantic basemodel的follwoing代码:

from pydantic import BaseModel, validator

class User(BaseModel, frozen=True):
    id_key: int
    user_id: int

    @validator('user_id')
    def id_check(cls, v, values):
        if v > 2 * values['id_key'] + 1:
            raise ValueError('id check failed.')
        return v

user_dict = {'user_id': 10, 'id_key': 60}
u = User(**user_dict)

现在,在我的应用程序中,我真的不希望id_key是一个u之类的模型实例中的常规,可访问的字段 - 其唯一目的是验证user_id。就我的示例而言,是否有一种方法可以访问id_key用于验证目的,但没有标准字段?

Consider the follwoing code illustrating use of the pydantic BaseModel with validation:

from pydantic import BaseModel, validator

class User(BaseModel, frozen=True):
    id_key: int
    user_id: int

    @validator('user_id')
    def id_check(cls, v, values):
        if v > 2 * values['id_key'] + 1:
            raise ValueError('id check failed.')
        return v

user_dict = {'user_id': 10, 'id_key': 60}
u = User(**user_dict)

Now, in my application, I don't really want id_key to be a regular, accessible field in model instances like u--its sole purpose is for validating user_id. For my example, is there a way to have access to id_key for validation purposes but not have it be a standard field?

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

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

发布评论

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

评论(1

女皇必胜 2025-02-09 19:54:50

value您在id_check函数中具有的参数是属性的内部dict 已经验证的实例,如果您需要具有id_key仅在实例化时间进行检查,而不是在此之后,您可以简单地从value中删除它。

from pydantic import BaseModel, validator

class User(BaseModel, frozen=True):
    id_key: int
    user_id: int

    @validator('user_id')
    def id_check(cls, v, values):
        if v > 2 * values['id_key'] + 1:
            raise ValueError('id check failed.')
        values.pop('id_key')
        return v
user_dict = {'user_id': 10, 'id_key': 60}
u = User(**user_dict)
print(u)
# output:
# user_id=10

我想为您的代码提出一个其他改进:在当前状态下,pydantic在返回验证错误之前运行所有字段的验证,如果您将某些内容完全无效,则> id_key>例如,例如“ ABC”,或省略它,它不会添加到valueuser_id的验证将使用keyError崩溃:'id_key',吞咽所有验证过程的其余部分,并没有返回明智的消息。

user_dict = {'user_id': 10, 'id_key': 'abc'}
u = User(**user_dict)
# output:
# KeyError: 'id_key'

这不是很明确,如果您期望pydantic vilenationError,可能会导致应用程序问题。您可能需要检查id_key确实存在于value中,并清洁错误(如果不是)。

from pydantic import BaseModel, validator

class User(BaseModel, frozen=True):
    id_key: int
    user_id: int

    @validator('user_id')
    def id_check(cls, v, values):
        if 'id_key' not in values or v > 2 * values['id_key'] + 1:
            raise ValueError('id check failed.')
        values.pop('id_key')
        return v
user_dict = {'user_id': 10, 'id_key': 'abc'}
u = User(**user_dict)
# output:
# pydantic.error_wrappers.ValidationError: 2 validation errors for User
# id_key
#   value is not a valid integer (type=type_error.integer)
# user_id
#   id check failed.(type=value_error)

The values argument you have in your id_check function being the internal dict of attributes already validated for your instance, if you need to have id_key only at instantiation time for checking and not after that, you could simply remove it from values.

from pydantic import BaseModel, validator

class User(BaseModel, frozen=True):
    id_key: int
    user_id: int

    @validator('user_id')
    def id_check(cls, v, values):
        if v > 2 * values['id_key'] + 1:
            raise ValueError('id check failed.')
        values.pop('id_key')
        return v
user_dict = {'user_id': 10, 'id_key': 60}
u = User(**user_dict)
print(u)
# output:
# user_id=10

There is one additional improvement I'd like to suggest for your code: in its present state, as pydantic runs the validations of all the fields before returning the validation errors, if you pass something completely invalid for id_key like "abc" for example, or omit it, it won't be added to values, and the validation of user_id will crash with KeyError: 'id_key', swallowing all the rest of the validation process and returning no sensible message.

user_dict = {'user_id': 10, 'id_key': 'abc'}
u = User(**user_dict)
# output:
# KeyError: 'id_key'

This is not very explicit, and might cause issues with your application if you expect a pydantic ValidationError. You might want to check that id_key is indeed present in values and raise the error cleanly if not.

from pydantic import BaseModel, validator

class User(BaseModel, frozen=True):
    id_key: int
    user_id: int

    @validator('user_id')
    def id_check(cls, v, values):
        if 'id_key' not in values or v > 2 * values['id_key'] + 1:
            raise ValueError('id check failed.')
        values.pop('id_key')
        return v
user_dict = {'user_id': 10, 'id_key': 'abc'}
u = User(**user_dict)
# output:
# pydantic.error_wrappers.ValidationError: 2 validation errors for User
# id_key
#   value is not a valid integer (type=type_error.integer)
# user_id
#   id check failed.(type=value_error)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文