python - how to make all field optional with alias name? - Stack Overflow

I am followingto create my model optional.I created function to get base class annotations.def get_

I am following to create my model optional.

I created function to get base class annotations.

def get_annotations(main_cls):
    ret_val = main_cls.__annotations__
    for base_cls in main_cls.__bases__:
        if base_cls != BaseModel:
            ret_val.update(get_annotations(base_cls))
    return ret_val

and created optional model as

OptionalClientModel = create_model(
    "OptionalClientModel",
    **{k: (Optional[v], None) for k, v in get_annotations(ClientModel).items()})

The original classes are as below

from typing import Annotated
from bson import ObjectId

from pydantic import Field
from pydantic import EmailStr
from pydantic import BaseModel
from pydantic import BeforeValidator
from pydantic import ConfigDict
from pydantic import AwareDatetime
from pydantic import field_validator

# Represents an ObjectId field in the database.
# It will be represented as a `str` on the model so that it can
# be serialized to JSON.
PyObjectId = Annotated[str, BeforeValidator(str)]

class DBTableBase(BaseModel):
    # The primary key for the Table, stored as a `str` on the instance.
    # This will be aliased to `_id` when sent to MongoDB,
    # but provided as `id` in the API requests and responses.
    id: PyObjectId | None = Field(alias="_id",
                                  serialization_alias="id",
                                  default=None)
    model_config = ConfigDict(
        json_encoders={ObjectId: str},
        json_schema_extra={
            "example": {
                "id": "BSON_ID"
            }
        },
    )

class ClientModel(DBTableBase):
    first_name: str
    last_name: str

When I want model with all optional value, I can use OptionalClientModel.

The issue is, id in OptionalClientModel has no alias.

How to create optional with alias?

I am following https://stackoverflow/a/77851176/243031 to create my model optional.

I created function to get base class annotations.

def get_annotations(main_cls):
    ret_val = main_cls.__annotations__
    for base_cls in main_cls.__bases__:
        if base_cls != BaseModel:
            ret_val.update(get_annotations(base_cls))
    return ret_val

and created optional model as

OptionalClientModel = create_model(
    "OptionalClientModel",
    **{k: (Optional[v], None) for k, v in get_annotations(ClientModel).items()})

The original classes are as below

from typing import Annotated
from bson import ObjectId

from pydantic import Field
from pydantic import EmailStr
from pydantic import BaseModel
from pydantic import BeforeValidator
from pydantic import ConfigDict
from pydantic import AwareDatetime
from pydantic import field_validator

# Represents an ObjectId field in the database.
# It will be represented as a `str` on the model so that it can
# be serialized to JSON.
PyObjectId = Annotated[str, BeforeValidator(str)]

class DBTableBase(BaseModel):
    # The primary key for the Table, stored as a `str` on the instance.
    # This will be aliased to `_id` when sent to MongoDB,
    # but provided as `id` in the API requests and responses.
    id: PyObjectId | None = Field(alias="_id",
                                  serialization_alias="id",
                                  default=None)
    model_config = ConfigDict(
        json_encoders={ObjectId: str},
        json_schema_extra={
            "example": {
                "id": "BSON_ID"
            }
        },
    )

class ClientModel(DBTableBase):
    first_name: str
    last_name: str

When I want model with all optional value, I can use OptionalClientModel.

The issue is, id in OptionalClientModel has no alias.

How to create optional with alias?

Share edited Mar 10 at 5:21 NPatel asked Mar 7 at 16:14 NPatelNPatel 21.4k17 gold badges100 silver badges163 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

With the following approach you can pass the FieldInfo objects from the original model to the new dynamically created model while giving the annotation an extra | None.

OptionalClientModel = create_model(
    "OptionalClientModel",
    **{k: (v.annotation | None, v) for k, v in ClientModel.model_fields.items()})

Edit: To set a default value of None as well you have to mutate the FieldInfo object before passing them to the create_model function. You also may have to copy the FieldInfo object on beforehand. Normally it wouldn't change anything but I am almost sure (didn't test it) that if you are calling model_rebuild on the original model somewhere the changes on the FieldInfo objects will be reflected on the rebuilt pydantic core schema.

field_infos = {}
for field_name, field_info in ClientModel.model_fields.items():
    field_info_copy = copy(field_info)
    field_info_copy.default = None
    field_infos[field_name] = field_info_copy

OptionalClientModel = create_model(
    "OptionalClientModel", **{k: (v.annotation | None, v) for k, v in field_infos.items()}
)

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744918459a4600981.html

相关推荐

  • python - how to make all field optional with alias name? - Stack Overflow

    I am followingto create my model optional.I created function to get base class annotations.def get_

    1天前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信