#python #pydantic
Вопрос:
У меня есть модель Pydantic, которая в основном представляет собой список других моделей, таких как:
class Thing(BaseModel):
_api: Api = PrivateAttr()
id: int
name: str
class ThingList(BaseModel):
_api: API = PrivateAttr()
__root__ = List[Thing]
Эти вещи анализируются из содержимого JSON вызовов API, которые я выполняю для внешнего API, например:
def some_method_somewhere(self, api, **other_args)
...
response = await api.send('GET', url)
return ThingList(__root__=response, api=api)
Однако я не вижу, как я могу заставить экземпляр Thing
модели Pydantic получить api
аргумент.
Единственный простой способ , который я вижу, — это чтобы какая-то функция возвращала глобальное значение, из которого я могу позвонить PrivateAttr(default_factory=func)
, но это пахнет.
Эта функциональность должна быть как можно более общей. В настоящее время список вещей можно заменить обычным списком, выполнив итерацию по объекту ответа (не стесняйтесь притворяться, что он исходит из запросов), но это не гарантируется в будущем. (На самом деле, вполне вероятно, что другие атрибуты будут поступать из API, которые, возможно, потребуется интегрировать в ThingList).
Решением моей мечты было бы расширение метода где-нибудь в классе ThingList, но я не могу найти, как это делает Pydantic.
Ответ №1:
Вы можете обновить частные атрибуты вложенных объектов в __init__
методе включения модели:
class Thing(BaseModel):
_api: str = PrivateAttr()
id: int
name: str
class ThingList(BaseModel):
_api: str = PrivateAttr()
__root__: List[Thing]
def __init__(self, *, api, **data):
super().__init__(**data)
self._api = api
for item in self.__root__:
item._api = api
Комментарии:
1. Это многообещающе. Однако не возникнет ли у меня проблем с валидаторами, потому что его не существует при инициализации?
2. Возможно, в случае валидаторов было бы неплохо увидеть минимальный пример вашего варианта использования.
3. Я думал о валидаторах pydantic по умолчанию. Но я запустил код с вашим предложением, и они не жалуются на назначение после создания экземпляра. Так что все в порядке.