shi*_*asu 5 python pydantic fastapi
我有两个像这样的 pydantic 课程。
class Parent(BaseModel):
id: int
name: str
email: str
class ParentUpdate(BaseModel):
id: Optional[int]
name: Optional[str]
email: Optional[str]
Run Code Online (Sandbox Code Playgroud)
这两者实际上是相同的,但Parent
该类要求所有字段。我想Parent
在 FastAPI 中使用POST 请求正文的类,因此所有字段都应该是必需的。但我想将后者用于 PUT 请求正文,因为用户可以设置选择性字段而其余字段保持不变。我已经查看了必需的可选字段,但它们与我想要做的不符。
如果有一种方法可以继承Parent
该类ParentUpdate
并修改其中的所有字段Parent
以Optional
减少混乱。此外,类中存在一些验证器Parent
,我必须在ParentUpdate
类中重写这些验证器,但我也想避免这些验证器。
有没有办法做到这一点?谢谢。
sha*_*all 19
您可以将子类中的可选字段设置为必填字段,但不能将子类中的必填字段设置为可选字段。在 fastapi 作者 tiangolo 的样板项目中,他在示例中使用了这样的模式:
class ParentBase(BaseModel):
"""Shared properties."""
name: str
email: str
class ParentCreate(ParentBase):
"""Properties to receive on item creation."""
# dont need id here if your db autocreates it
pass
class ParentUpdate(ParentBase):
"""Properties to receive on item update."""
# dont need id as you are likely PUTing to /parents/{id}
# other fields should not be optional in a PUT
# maybe what you are wanting is a PATCH schema?
pass
class ParentInDBBase(ParentBase):
"""Properties shared by models stored in DB - !exposed in create/update."""
# primary key exists in db, but not in base/create/update
id: int
class Parent(ParentInDBBase):
"""Properties to return to client."""
# optionally include things like relationships returned to consumer
# related_things: List[Thing]
pass
class ParentInDB(ParentInDBBase):
"""Additional properties stored in DB."""
# could be secure things like passwords?
pass
Run Code Online (Sandbox Code Playgroud)
是的,我同意这非常冗长,但我希望不是这样。您仍然可能最终得到更特定于 UI 中特定表单的其他架构。显然,您可以删除其中一些,因为它们在本示例中不是必需的,但根据数据库中的其他字段,可能需要它们,或者您可能需要设置默认值、验证等。
根据我对验证器的经验,您必须重新声明它们,但您可以使用共享函数,即:
def clean_article_url(cls, v):
return clean_context_url(v.strip())
class MyModel(BaseModel):
article_url: str
_clean_url = pydantic.validator("article_url", allow_reuse=True)(clean_article_url)
Run Code Online (Sandbox Code Playgroud)
ela*_*no7 10
覆盖字段是可能且容易的。(有人提到不可能将必填字段覆盖为可选字段,但我不同意)。
这个例子运行没有任何问题:
class Parent(BaseModel):
id: int
name: str
email: str
class ParentUpdate(Parent): ## Note that this inherits 'Parent' class (not BaseModel)
id: Optional[int] # this will convert id from required to optional
Run Code Online (Sandbox Code Playgroud)
正如在类似问题的回答中已经概述的那样,我正在使用以下方法(归功于 Aron Podrigal):
import inspect
from pydantic import BaseModel
def optional(*fields):
"""Decorator function used to modify a pydantic model's fields to all be optional.
Alternatively, you can also pass the field names that should be made optional as arguments
to the decorator.
Taken from https://github.com/samuelcolvin/pydantic/issues/1223#issuecomment-775363074
"""
def dec(_cls):
for field in fields:
_cls.__fields__[field].required = False
return _cls
if fields and inspect.isclass(fields[0]) and issubclass(fields[0], BaseModel):
cls = fields[0]
fields = cls.__fields__
return dec(cls)
return dec
Run Code Online (Sandbox Code Playgroud)
在您的示例中,您将像这样使用它:
@optional
class ParentUpdate(Parent):
pass
Run Code Online (Sandbox Code Playgroud)