如何在Pydantic中实现AtBat模型ab_number字段的自动递增
如何在Pydantic中实现AtBat模型ab_number字段的自动递增
嘿,我来帮你搞定这个问题!你的代码报错其实是因为Pydantic对私有属性的处理逻辑和你预期的不一样,咱们一步步来修正:
问题根源
你定义的_counter: int = 1,在Pydantic规则里,以单下划线开头的属性会被自动转换成ModelPrivateAttr类型,这不是普通的整数变量,所以你没法直接对它做+=算术操作,这就是报错TypeError: unsupported operand type(s) for +=: 'ModelPrivateAttr' and 'int'的原因。
解决方案1:用ClassVar标记类计数器
我们可以用ClassVar来告诉Pydantic:这个变量是类级别的,不属于模型的字段,这样它就会被当作普通整数变量处理,就能正常递增了。同时你也不用再把ab_number设为None,可以直接设为必填字段。
修改后的完整代码:
import requests from pydantic import BaseModel, Field from typing import List, ClassVar url = "https://statsapi.mlb.com/api/v1.1/game/745707/feed/live/diffPatch" response = requests.get(url).json() class AtBat(BaseModel): ab_number: int = Field(...) # 现在可以设为必填,无需默认None _counter: ClassVar[int] = 1 # 用ClassVar标记为类变量,不参与模型字段校验 def __init__(self, **data): super().__init__(**data) self.ab_number = AtBat._counter AtBat._counter += 1 # print(self.ab_number) # 调试时可以打开看递增情况 class Plays(BaseModel): allPlays: List[AtBat] data = Plays(**response['liveData']['plays']) # 验证结果(可选) for idx, atbat in enumerate(data.allPlays, 1): assert atbat.ab_number == idx print("所有ab_number都按顺序递增啦!")
解决方案2:外部手动赋值(更直观)
如果你不想改动模型类的初始化逻辑,也可以在解析数据前,手动给每条play加上递增的ab_number:
import requests from pydantic import BaseModel, Field from typing import List url = "https://statsapi.mlb.com/api/v1.1/game/745707/feed/live/diffPatch" response = requests.get(url).json() class AtBat(BaseModel): ab_number: int = Field(...) # 直接定义必填字段 class Plays(BaseModel): allPlays: List[AtBat] # 手动给每条数据加递增的ab_number plays_data = response['liveData']['plays']['allPlays'] for idx, play in enumerate(plays_data, 1): play['ab_number'] = idx data = Plays(allPlays=plays_data)
这两种方法都能实现你想要的「类似MySQL主键自动递增」的效果,你可以根据自己的代码风格选一种来用~
备注:内容来源于stack exchange,提问作者Newman
相关产品推荐
相关产品推荐

