用于部分更新的 Pydantic 输入模型

Sam*_*bhi 12 python pydantic

我正在使用 Pydantic 来验证服务器中的数据输入。悬垂模型:

  • 用户:用于公共字段
  • UserIn:用户输入数据以创建新帐户
  • UserInDB:哈希密码并包含额外字段,例如created_at
  • UserOut:输出创建/更新的用户数据

现在我如何利用该模型UserIn进行用户帐户部分更新?以便None排除字段。或者我必须再次重写它并使每个字段都是可选的?

class User(BaseModel):

    name_first :          str = Field(...)
    name_last :           Optional[str] = None
    mobile :              int = Field(..., description="It has to be 8 digits and starts with either 9 or 7", example="99009900")
    
    email :               Optional[EmailStr] = None
    
    gender:               Literal['m', 'f'] = Field(..., example="m")
    birth_date:           datetime.date
    preferred_language :  Literal['ar', 'en'] = Field(..., example="ar")
    newsletter :          bool = Field(...)


    @validator('mobile')
    def number_has_to_start_with_9_or_7(cls, v):
        if str(v)[:1] !="9" and str(v)[:1] !="7":
            raise ValueError('Mobile number must start with 9 or 7')
        if len(str(v)) !=8:
            raise ValueError('Mobile number must be 8 digits')
        return v


class UserIn(User):
    password: str = Field(...)

class UserInDB(UserIn):
    mobile_otp:           int = Field(...)
    bitrole:              int = Field(...)
    created_at:           datetime.datetime
    updated_at:           datetime.datetime

class UserOut(User):
    id:                   int
    mobile_otp:           int
    bitrole:              int
    mobile_confirmed :    bool
    email_confirmed :     bool
    disabled :            bool
    created_at:           datetime.datetime
    updated_at:           datetime.datetime

    class Config:
        orm_mode = True
Run Code Online (Sandbox Code Playgroud)

lsa*_*abi 11

不幸的是,这是很多人(包括我)已经面临的问题。

据我所知,没有简单的方法可以开箱即用地处理它。

以下是 github 上提出的一些解决方案,尽管并不完全,但可以绕过该问题

https://github.com/samuelcolvin/pydantic/issues/990#issuecomment-645961530

我的解决方案

我将 pydantic 与fastapi一起使用,资源的部分更新是很常见的。由于 pydantic 的限制,我要求用户重新提交所有值,正确填写 pydantic 模型,然后更新所有可以更新的字段。

我知道这并不理想,但它似乎有效

更新

我找到了另一种可能的解决方案。基本上,检索旧数据,更新它,然后写入更新的数据(比我的解决方案好得多)。

请参阅 fastapi 文档https://fastapi.tiangolo.com/tutorial/body-updates/#partial-updates-with-patch

警告: pydantic 中当前未实现嵌套对象的部分更新。请参阅https://github.com/pydantic/pydantic/issues/4177

  • FastAPI 方法对我来说是可以接受的。如果您注意到,Pydantic 更新模型/模式中的所有字段都是可选的。这里的第一点是您不能使用 Pydantic 创建模型进行部分更新。必须有第二个模型,所有字段都是可选的。第二点是您不需要像该示例中那样检索存储的数据。您可以使用查询更新简单地部分更新数据库记录。 (2认同)