使用 Fastapi 的 class 变量更改 pydantic 模型 Field() 参数

Changing pydantic model Field() arguments with class variables for Fastapi

我对 python 中的 class 继承有点陌生,尤其是当涉及到使用 class 属性时。在这种情况下,我使用 class 属性 来更改 pydantic 的 Field() 函数中的参数。如果我的 class 包含它自己的构造函数,这不会太难做到,但是,我的 class User1 是从 pydantic 的 BaseModel 继承的。 这个想法是我希望能够在创建实例之前更改 class 属性

请看下面的一些示例代码:

from pydantic import Basemodel, Field   

class User1(BaseModel):
    _set_ge = None # create class attribute
    item: float = Field(..., ge=_set_ge)

    # avoid overriding BaseModel's __init__
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    
User1._set_ge = 0 # setting the class attribute to a new value
instance = User1(item=-1)
print(instance) # item=-1.0

使用 instance = User1(item=-1) 创建实例时,我希望抛出验证错误,但它却通过了验证,只是 returns item 值。

如果我有自己的构造函数,那么更改 _set_ge 不会有什么问题,但是由于 User1BaseModel 继承了这个构造函数,事情就有点复杂了。

最终目标是将此 class 添加到 fastapi 端点,如下所示:

from fastapi import Fastapi
from schemas import User1    

class NewUser1(User1):
      pass

NewUser1._set_ge = 0    

@app.post("/")
def endpoint(request: NewUser1):
    return User1.item

为了减少代码重复,我旨在使用此方法轻松更改 Field() 参数。如果有更好的方法,我也很乐意考虑。

此问题与 this 未回答的问题密切相关。

最后,@hernán-alarcón 提出的 @validator 提议可能是最好的方法。例如:

from pydantic import Basemodel, Field, NumberNotGeError
from typing import ClassVar   

class User(BaseModel):
    _set_ge = ClassVar[float] # added the ClassVar typing to make clearer, but the underscore should be sufficient
    item: float = Field(...)

    @validator('item')
    def limits(cls, v):
        limit_number = cls._set_ge
        if v >= limit_number:
            return v
        else:
            raise NumberNotGeError(limit_value=limit_number)
        
    
class User1(User)
     _set_ge = 0 # setting the class attribute to a new value

instance = User1(item=-1) # raises the error