Создание объектов с идентификатором и заполнение других полей - PullRequest
0 голосов
/ 15 марта 2020

Я хочу создать объект Pydanti c только с идентификатором, а затем заполнить другие поля на основе идентификатора.
Я пробовал 2 разных подхода, валидатор, а также после инициализации. Не сработало, поэтому.

Общий код:

from pydantic import BaseModel, validator

obj_list = [
    {'id': 1, 'name': 'a', 'desc': 'desc1'},
    {'id': 2, 'name': 'b', 'desc': 'desc2'},
    {'id': 3, 'name': 'c', 'desc': 'desc3'}
]

Решение 1:

class Obj(BaseModel):
    id: int
    name: str = None
    desc: str = None

    @validator('id')
    def validate_exists(cls, v):
        items = [h for h in obj_list if h['id'] == v]
        if len(items) == 0:
            raise ValueError('id doesnt exist')
        return v

    def __post_init__(self):
        item = [h for h in obj_list if h['name'] == v][0]
        self.name = item['name']
        self.desc = item['desc']

Obj(id=1)
# <Obj id=1 name=None desc=None>

Решение 2:

class Obj(BaseModel):
    name: str = None
    desc: str = None
    id: int

    @validator('id')
    def validate_exists(cls, v, values):
        items = [h for h in obj_list if h['id'] == v]
        if len(items) == 0:
            raise ValueError('id doesnt exist')
        item = items[0]
        values['name'] = item['name']
        values['desc'] = item['desc']
        return v

Obj(id=1)
# <Obj name=None desc=None id=1>

Я чувствую как будто это выполнимо Я прочитал документацию Pydanti c и FastApi, но не смог найти ничего подходящего для этого. Итак, как я могу создавать объекты, используя только идентификаторы, а затем заполнять поля, используя БД или другой объект?

Ответы [ 2 ]

1 голос
/ 18 марта 2020

Я решил проблему, используя root_validator в пиданти c.

from pydantic import BaseModel, root_validator

obj_list = [
    {'id': 1, 'name': 'a', 'desc': 'desc1'},
    {'id': 2, 'name': 'b', 'desc': 'desc2'},
    {'id': 3, 'name': 'c', 'desc': 'desc3'}
]
class Obj(BaseModel):
    id: int
    name: str = None
    desc: str = None

    @root_validator(pre=True)
    def validate_exists(cls, values):
        if 'id' not in values:
            raise ValueError("id doesn't exist in the fields")
        items = [h for h in obj_list if h['id'] == values['id']]
        if len(items) == 0:
            raise ValueError(f"there is no obj with id {values['id']}")
        return items[0]

Obj(id=1)
0 голосов
/ 16 марта 2020

__post_init__ не существует, я думаю, вы перепутали с классами данных.

Pydanti c проверка должна происходить один раз, когда вы создаете объект модели. Хотя вы можете обойти это, используя Config.validate_assignment.

Для этого есть два решения:

  1. Создайте каждую модель с помощью id, затем используйте присвоение атрибута для установки других полей. Это будет медленнее, и я думаю, что это неправильный подход.
  2. Не создавайте модели, пока у вас не будут все данные, необходимые для создания модели. Я бы предположил, что это лучший подход.
...