我有两门课:
class UserCreate(BaseModel):
avatar: HttpUrl = Field(..., description="Avatar", example="https://picsum.photos/200")
name: str = Field(..., max_length=20, description="A single word", example='Ivan')
birthdate: datetime_date = Field(..., description="Two digits", example='1980-1-1')
comment: Optional[str] = Field(..., max_length=512, description="lorem ipsum about a user", example='blah blah')
并且我想创建一个 UserUpdate
类,该类将从父类继承每个字段并使其成为 Optional
。
Result 类必须如下所示:
class UserUpdate(BaseModel):
avatar: typing.Optional[HttpUrl] = Field(..., description="Avatar", example="https://picsum.photos/200")
name: typing.Optional[str] = Field(..., max_length=20, description="A single word", example='Ivan')
birthdate: typing.Optional[datetime_date] = Field(..., description="Two digits", example='1980-1-1')
comment: typing.Optional[str] = Field(..., max_length=512, description="lorem ipsum about a user", example='blah blah')
但显然,我想自动制作,例如:
class UserUpdate(UserCreate):
def foo(fields_from_user_create):
for fields in fields_from_user_create:
field = typing.Optional(field)
答案 0 :(得分:1)
我正在使用以下方法(归功于 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
在您的示例中,您可以这样使用它:
@optional
class UserUpdate(UserCreate):
pass
答案 1 :(得分:0)
直接来自PrettyWood的解决方案
<块引用>这是一种方法
from copy import deepcopy
from typing import Optional, Type, TypeVar
from pydantic import BaseModel, create_model
BaseModelT = TypeVar('BaseModelT', bound=BaseModel)
def to_optional(model: Type[BaseModelT], name: Optional[str] = None) -> Type[BaseModelT]:
"""
Create a new BaseModel with the exact same fields as `model`
but making them all optional
"""
field_definitions = {}
for name, field in model.__fields__.items():
optional_field_info = deepcopy(field.field_info)
# Do not change default value of fields that are already optional
if optional_field_info.default is ...:
optional_field_info.default = None
field_type = model.__annotations__.get(name, field.outer_type_)
field_definitions[name] = (field_type, optional_field_info)
return create_model(name or f'Optional{model.__name__}', **field_definitions) # type: ignore[arg-type]
<块引用>
希望有帮助;)