简体   繁体   中英

Creating a Pydantic model dynamically from a Python dataclass

I'd like to dynamically create a Pydantic model from a dataclass, similar to how you can dynamically create a Marshmallow schema from a dataclass as in marshmallow-dataclass or https://stevenloria.com/dynamic-schemas-in-marshmallow/ . Is there already a library or easy way to do this?

Some background - I prefer using a dataclass in my business logic rather than using the Pydantic model directly. I use the Pydantic model for serializing/deserializing data with camel-cased fields within my FastAPI app only. However, I find myself basically duplicating the dataclass definition which isn't efficient.

Sample Input:

from typing import List

from dataclasses import dataclass


@dataclass
class Item:
    id: int = None
    stuff: str = None
    height: float = None


@dataclass
class Bag:
    id: int = None
    name: str = None
    things: List[Item] = None


@dataclass
class Basket:
    id: int = None
    recipient: str = None
    bags: List[Bag] = None
    best_item: Item = None

Desired output:

from typing import List

from pydantic.main import BaseModel


def camel_case_converter(value: str):
    parts = value.lower().split('_')
    return parts[0] + ''.join(i.title() for i in parts[1:])


class CamelBaseModel(BaseModel):
    class Config:
        alias_generator = camel_case_converter


class Item(CamelBaseModel):
    id: int = None
    stuff: str = None
    height: float = None


class Bag(CamelBaseModel):
    id: int = None
    name: str = None
    things: List[Item] = None


class Basket(CamelBaseModel):
    id: int = None
    recipient: str = None
    bags: List[Bag] = None
    best_item: Item = None

Maybe something like this? (from https://github.com/samuelcolvin/pydantic/issues/1967#issuecomment-742698281 )

from typing import Type

from pydantic import BaseModel
from pydantic.dataclasses import dataclass as pydantic_dataclass
from typing import List

from dataclasses import dataclass


def model_from_dataclass(kls: 'StdlibDataclass') -> Type[BaseModel]:
    """Converts a stdlib dataclass to a pydantic BaseModel"""
    return pydantic_dataclass(kls).__pydantic_model__

@dataclass
class Item:
    id: int = None
    stuff: str = None
    height: float = None

ItemBaseModel = model_from_dataclass(Item)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM