pydanticで_から始まるクラス変数を利用できないので、利用できるようにする
通常の問題がないパターン
from pydantic import BaseModel, Field class Users(BaseModel): id: str = Field(None) name: str = Field(None) data: str = Field(None) u = Users(id="a", name="b", data="data") # id='a' name='b' data='data' print(u) # {'id': 'a', 'name': 'b', 'data': 'data'} print(u.dict())
問題があるパターン
- _idの様に変数名が_から始まる場合、pydanticでは値を入れられるが取得ができなくなる
- private変数として扱われて外部から参照できなくなる?
from pydantic import BaseModel, Field class Users(BaseModel): _id: str = Field(None) name: str = Field(None) data: str = Field(None) u = Users(_id="a", name="b", data="data") # name='b' data='data' print(u) # {'name': 'b', 'data': 'data'} print(u.dict())
_から始まる変数を利用できるようにする
方法1. Field(alias)を利用する
- pydanticで標準で用意されているFieldにaliasを割り当てる方法で変数を定義し、dictに変換する時にaliasに指定した値で変換する
from pydantic import BaseModel, Field class Users(BaseModel): id: str = Field(None, alias="_id") name: str = Field(None) data: str = Field(None) u = Users(_id="a", name="b", data="data") # id='a' name='b' data='data' print(u) # {'_id': 'a', 'name': 'b', 'data': 'data'} print(u.dict(by_alias=True))
方法2. pydanticのdefにモンキーパッチを当てて問題を回避する
- Field(alias)は使えないとか、使いたくないとか理由がある人向け
_から始まる変数名が利用できないことについて問題だと思っている人はいるようでGitHubにisssuが上がっている
Class attributes starting with underscore do not support assignment #288issueの中にあるpydanticにmonkey patchを当てて_を利用する方法が記載されている
https://github.com/samuelcolvin/pydantic/issues/288#issuecomment-629752056以下のコードを記述すると_から始まる変数を利用できるようになる
# monkey patch to get underscore fields def is_valid_field(name:str): if not name.startswith('__'): return True elif name == '__root__': return True pydantic.main.is_valid_field = is_valid_field
モンキーパッチを当てたソース
- これでField(alias)を使わなくても問題なく_から始まる変数名を利用できるようになる
- こだわりがないのなら方法1のField(alias)を使った方がいいと思う
import pydantic from pydantic import BaseModel, Field def is_valid_field(name: str): if not name.startswith("__"): return True elif name == "__root__": return True pydantic.main.is_valid_field = is_valid_field class Users(BaseModel): _id: str = Field(None) name: str = Field(None) data: str = Field(None) u = Users(_id="a", name="b", data="data") # _id='a' name='b' data='data' print(u) # {'_id': 'a', 'name': 'b', 'data': 'data'} print(u.dict())