如何建模Pydantic模型以接受IP作为DICE或CIDR字符串

发布于 2025-01-24 13:03:34 字数 1595 浏览 1 评论 0原文

在Pydantic中,是否可以通过而不是dict 的值,仍然可以通过基本模型?

我有一种情况,我希望能够处理CIDR格式化的IP(例如1.2.3.4/32)并仍然返回有效的模型IPv4。

在下面的示例中,我初始化了3个IP。 对于第三IP,我通过了CIDR格式的STR,并希望能够返回有效的IPv4模型。

@Root_Validator仅用于打印传递的值。

您可以看到,键“ IP3”的第三值未由类处理。错误是

pydantic.Error_wrappers.ValidationError:IPS的1个验证错误 ip3
值不是有效的dict(type = type_error.dict)


代码

from pydantic import BaseModel, root_validator


class Ipv4(BaseModel):
    """
    Validate structure of IPv4
    """
    address: str
    subnet_mask: int = 22

    @root_validator(pre=True)
    def handle_address_from_cidr_notation(cls, values):
        print(f'These are the values passed into the model: {values}')
        return values

class Ips(BaseModel):
    ip1: Ipv4
    ip2: Ipv4
    ip3: Ipv4




ips_dict = {
    'ip1': {'address': '1.1.1.1', 'subnet_mask': 24},
    'ip2': {'address': '1.1.1.1'},
    'ip3': '1.1.1.1',
}

ips: Ips = Ips(**ips_dict)

print(ips.ip1)
print(ips.ip2)
print(ips.ip3)

输出

These are the values passed into the model: {'address': '1.1.1.1', 'subnet_mask': 24}
These are the values passed into the model: {'address': '1.1.1.1'}
Traceback (most recent call last):
  File "playground/test_pydantic_13.py", line 30, in <module>
    ips: Ips = Ips(**ips_dict)
  File "pydantic/main.py", line 406, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for Ips
ip3
  value is not a valid dict (type=type_error.dict)

In Pydantic, is it possible to pass a value that is not a dict and still make it go through a BaseModel?

I have a case where I want to be able to process a CIDR formatted IP (e.g. 1.2.3.4/32) and still return a valid model Ipv4.

In the example below I initialize 3 IPs.
For the 3rd IP I pass a CIDR formatted str and want to be able to return a valid Ipv4 model.

the @root_validator is only used to print the passed values.

You can see that the 3rd value for key 'ip3' is not processed by the class. The error is

pydantic.error_wrappers.ValidationError: 1 validation error for Ips
ip3
value is not a valid dict (type=type_error.dict)


Code

from pydantic import BaseModel, root_validator


class Ipv4(BaseModel):
    """
    Validate structure of IPv4
    """
    address: str
    subnet_mask: int = 22

    @root_validator(pre=True)
    def handle_address_from_cidr_notation(cls, values):
        print(f'These are the values passed into the model: {values}')
        return values

class Ips(BaseModel):
    ip1: Ipv4
    ip2: Ipv4
    ip3: Ipv4




ips_dict = {
    'ip1': {'address': '1.1.1.1', 'subnet_mask': 24},
    'ip2': {'address': '1.1.1.1'},
    'ip3': '1.1.1.1',
}

ips: Ips = Ips(**ips_dict)

print(ips.ip1)
print(ips.ip2)
print(ips.ip3)

Output

These are the values passed into the model: {'address': '1.1.1.1', 'subnet_mask': 24}
These are the values passed into the model: {'address': '1.1.1.1'}
Traceback (most recent call last):
  File "playground/test_pydantic_13.py", line 30, in <module>
    ips: Ips = Ips(**ips_dict)
  File "pydantic/main.py", line 406, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for Ips
ip3
  value is not a valid dict (type=type_error.dict)

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

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

发布评论

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

评论(1

很酷不放纵 2025-01-31 13:03:34

这在Python 3.10上使用Pydantic 1.9
对于使用Pydantic 1.9的Python 3.6,使用

Union[Ipv4, Ipv4Cidr]

模型IPv4CIDR提供了一种验证方法,该方法将CIDR格式化的str分配以解决和subnet_mask并将新值传递给其继承的模型IPv4。

这允许以3种不同的方式传递IP:

  • IP地址 +子网掩码
  • IP地址仅
  • IP地址 /子网掩码 -

的CIDR符号代码输出。

from typing import Optional, Union

from pydantic import BaseModel



class Ipv4(BaseModel):
    """
    Validate structure of IPv4
    """
    address: str
    subnet_mask: Optional[int]


class Ipv4Cidr(Ipv4):
    """
    Validate structure of IPv4
    """

    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, value: str, field):
        if isinstance(value, str):
            try:
                address, subnet_mask = value.split('/')
                return Ipv4(address=address, subnet_mask=subnet_mask)
            except ValueError as ve:
                return Ipv4(address=value)
        else:
            return Ipv4(**value)



class Ips(BaseModel):
    ip1: Ipv4
    ip2: Union[Ipv4, Ipv4Cidr]
    ip3: Ipv4Cidr
    ip4: Union[Ipv4, Ipv4Cidr]


ips_dict = {
    'ip1': {'address': '1.1.1.1', 'subnet_mask': 24},
    'ip2': {'address': '2.2.2.2'},
    'ip3': '3.3.3.3/32',
    'ip4': '4.4.4.4/32',
}

ips: Ips = Ips(**ips_dict)

print(ips.ip1)
print(ips.ip2)
print(ips.ip3)
print(ips.ip4)

Python 3.10 + Pydantic 1.9

address='1.1.1.1' subnet_mask=24
address='2.2.2.2' subnet_mask=None
address='3.3.3.3' subnet_mask=32
address='4.4.4.4' subnet_mask=32

Python 3.6 + Pydantic 1.9

Traceback (most recent call last):
  File "playground/test_pydantic_13.py", line 50, in <module>
    ips: Ips = Ips(**ips_dict)
  File "pydantic/main.py", line 331, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for Ips
ip4
  value is not a valid dict (type=type_error.dict)

This works on Python 3.10 with pydantic 1.9
For Python 3.6 with pydantic 1.9, There is an error when using

Union[Ipv4, Ipv4Cidr]

Model Ipv4Cidr provides a validate method that splits the cidr formatted str to address and subnet_mask and passes the new values to Model Ipv4 which it inherits.

This allows for passing the IP in 3 different ways:

  • ip address + subnet mask
  • ip address only
  • ip address / subnet mask - cidr notation

Code

from typing import Optional, Union

from pydantic import BaseModel



class Ipv4(BaseModel):
    """
    Validate structure of IPv4
    """
    address: str
    subnet_mask: Optional[int]


class Ipv4Cidr(Ipv4):
    """
    Validate structure of IPv4
    """

    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, value: str, field):
        if isinstance(value, str):
            try:
                address, subnet_mask = value.split('/')
                return Ipv4(address=address, subnet_mask=subnet_mask)
            except ValueError as ve:
                return Ipv4(address=value)
        else:
            return Ipv4(**value)



class Ips(BaseModel):
    ip1: Ipv4
    ip2: Union[Ipv4, Ipv4Cidr]
    ip3: Ipv4Cidr
    ip4: Union[Ipv4, Ipv4Cidr]


ips_dict = {
    'ip1': {'address': '1.1.1.1', 'subnet_mask': 24},
    'ip2': {'address': '2.2.2.2'},
    'ip3': '3.3.3.3/32',
    'ip4': '4.4.4.4/32',
}

ips: Ips = Ips(**ips_dict)

print(ips.ip1)
print(ips.ip2)
print(ips.ip3)
print(ips.ip4)

Output for Python 3.10 + Pydantic 1.9

address='1.1.1.1' subnet_mask=24
address='2.2.2.2' subnet_mask=None
address='3.3.3.3' subnet_mask=32
address='4.4.4.4' subnet_mask=32

Output for Python 3.6 + Pydantic 1.9

Traceback (most recent call last):
  File "playground/test_pydantic_13.py", line 50, in <module>
    ips: Ips = Ips(**ips_dict)
  File "pydantic/main.py", line 331, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for Ips
ip4
  value is not a valid dict (type=type_error.dict)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文