pydantic 和 peewee 怎么优雅的协作呀?

现在遇到的一个问题就是,一个模型,要使用 pydantic 和 peewee 各自定义一次,比较繁琐,尤其是字段很多的时候

pydantic 模型

class ShortDramaModel(BaseModel):
    drama_name: str = Field(..., description="短剧名称")
    view_count: int | None = Field(None, description="播放数")
    drama_type: str | None = Field(None, description="类型(比如现代言情、历史古代)")
    available_episodes: int | None = Field(None, description="当前可看的集数")
    total_episodes: int | None = Field(None, description="总集数")
    is_finished: bool | None = Field(None, description="是否完结")
    online_micro_drama_record_number: str | None = Field(
        None, description="网微剧备案号")
    like_count: int | None = Field(None, description="点赞数")
    cover_image_url: str | None = Field(None, description="封面图链接")

peewee 模型

class ShortDramaModel(Model):
    drama_name = CharField(unique=True, null=False, verbose_name="短剧名称")
    view_count = IntegerField(null=True, verbose_name="播放数")
    drama_type = CharField(null=True, verbose_name="类型(比如现代言情、历史古代)")
    available_episodes = IntegerField(null=True, verbose_name="当前可看的集数")
    total_episodes = IntegerField(null=True, verbose_name="总集数")
    is_finished = BooleanField(null=True, verbose_name="是否完结")
    online_micro_drama_record_number = CharField(null=True, verbose_name="网微剧备案号")
    like_count = IntegerField(null=True, verbose_name="点赞数")
    cover_image_url = CharField(null=True, verbose_name="封面图链接")

    class Meta:
        database = db
阅读 317
1 个回答

基于 dataclass 的元模型方案,结合生成器自动创建 Pydantic 和 Peewee 模型:

from dataclasses import dataclass
from typing import Optional, Type, Dict
from pydantic import BaseModel, Field, create_model
from peewee import Model, CharField, IntegerField, BooleanField, SqliteDatabase

# 定义字段描述的类型
@dataclass
class FieldSpec:
    type: Type
    required: bool = True
    unique: bool = False
    description: str = ""

# 元模型:描述 ShortDrama 的字段
class ShortDramaMeta:
    fields: Dict[str, FieldSpec] = {
        "drama_name": FieldSpec(type=str, required=True, unique=True, description="短剧名称"),
        "view_count": FieldSpec(type=int, required=False, description="播放数"),
        "drama_type": FieldSpec(type=str, required=False, description="类型(比如现代言情、历史古代)"),
        "available_episodes": FieldSpec(type=int, required=False, description="当前可看的集数"),
        "total_episodes": FieldSpec(type=int, required=False, description="总集数"),
        "is_finished": FieldSpec(type=bool, required=False, description="是否完结"),
        "online_micro_drama_record_number": FieldSpec(type=str, required=False, description="网微剧备案号"),
        "like_count": FieldSpec(type=int, required=False, description="点赞数"),
        "cover_image_url": FieldSpec(type=str, required=False, description="封面图链接"),
    }

# Pydantic 模型生成器
def generate_pydantic_model(meta_class) -> Type[BaseModel]:
    pydantic_fields = {}
    for name, spec in meta_class.fields.items():
        field_type = spec.type if spec.required else Optional[spec.type]
        pydantic_fields[name] = (field_type, Field(..., description=spec.description) if spec.required else Field(None, description=spec.description))
    return create_model("ShortDramaModel", **pydantic_fields)

# Peewee 模型生成器
def generate_peewee_model(meta_class, db) -> Type[Model]:
    class PeeweeModel(Model):
        class Meta:
            database = db

    field_map = {str: CharField, int: IntegerField, bool: BooleanField}
    for name, spec in meta_class.fields.items():
        peewee_field = field_map[spec.type](
            null=not spec.required,
            unique=spec.unique,
            verbose_name=spec.description
        )
        setattr(PeeweeModel, name, peewee_field)
    return PeeweeModel

# 使用示例
db = SqliteDatabase("example.db")

# 生成模型
ShortDramaPydanticModel = generate_pydantic_model(ShortDramaMeta)
ShortDramaPeeweeModel = generate_peewee_model(ShortDramaMeta, db)

# 测试 Pydantic 模型
pydantic_instance = ShortDramaPydanticModel(drama_name="Example Drama")
print(pydantic_instance.dict())

# 测试 Peewee 模型
db.connect()
db.create_tables([ShortDramaPeeweeModel])
ShortDramaPeeweeModel.create(drama_name="Example Drama")
print(ShortDramaPeeweeModel.select().count())
db.close()

使用

1.定义新模型:只需创建一个新的 XxxMeta 类,填入字段定义。
2.生成模型:调用生成函数即可获得 Pydantic 和 Peewee 模型。
3.集成:直接在 FastAPI(用 Pydantic)或数据库操作(用 Peewee)中使用。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏