气派。如何在class中添加数据修改功能

Pydantic. How to add data alteration functions within the class

我刚开始学习 Pydantic 和 FastAPI。我的模型看起来像这样。

class Max70Text(BaseModel):
    __root__: constr(min_length=1,max_length=70) = Field(
        ...,
        description='Specifies a character string with a maximum length of 70 characters.'    
    )

如果我的字符串长度超过 70,我会在我的主程序中处理此 class 之外的截断函数。 我想在 class 本身内执行此操作只是为了保持整洁。 IE。如果将长度超过 70 的字符串传递给此 class,则返回的对象应自动从右侧截断其 str 值以匹配长度。

您可以使用 root_validator 根据您的约束解析传入数据:

class Max70Text(BaseModel):
    __root__: constr(min_length=1,max_length=70) = Field(
        ...,
        description='Specifies a character string with a maximum length of 70 characters.'
    )

    @staticmethod
    def truncate(v):
        return v[:70]

    @root_validator(pre=True)
    def len_validator(cls, values):
        values['__root__'] = cls.truncate(values['__root__'])
        return values

除了root types like above, pydantic allows you to create own custom data types,在某些情况下更方便。该演示尚未准备好生产:

from pydantic import BaseModel, Field


class TruncatedBase(str):
    limit: int

    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)

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

    @classmethod
    def truncate(cls, value: str):
        return value[:cls.limit] + "..." if len(value) > cls.limit else value

    @classmethod
    def validate(cls, v):
        if not isinstance(v, str):
            raise TypeError('string required')
        if not v:
            raise TypeError('empty string is not allowed')
        return cls(cls.truncate(v))

    def __repr__(self):
        return f'Max{self.limit}Text({super().__repr__()})'


def truncated_text(limit=10):
    return type('TruncatedText', (TruncatedBase,), {'limit': limit})


class Model(BaseModel):
    field1: truncated_text(limit=5) = Field(..., description="5 max")
    field2: truncated_text(limit=6) = Field(..., description="6 max")


print(Model(field1="1"*6, field2="1"*6))

输出:

field1=Max5Text('11111...') field2=Max6Text('111111')