Определение Pydantic (вложенной) модели

#python #json #fastapi #pydantic

#python #json #fastapi #pydantic

Вопрос:

Если я использую GET (с заданным идентификатором), я получаю JSON типа:

 {
    "data": {
        "id": "81",
        "ks": {
            "k1": 25,
            "k2": 5
        },
        "items": [
            {
                "id": 1,
                "name": "John",
                "surname": "Smith"
            },
            {
                "id": 2,
                "name": "Jane",
                "surname": "Doe"
            }
        ]
    },
    "server-time": "2021-12-09 14:18:40"
}
 

в конкретном случае (если идентификатор не существует):

 {
    "data": {
        "id": -1,
        "ks": "",
        "items": []
    },
    "server-time": "2021-12-10 09:35:22"
}
 

Я хотел бы создать Pydantic модель для управления этой структурой данных (я имею в виду формальное определение этих объектов).
Каков самый разумный способ управления этой структурой данных путем создания классов (возможно, вложенных)?

Ответ №1:

Если вам не нужна проверка данных, которая pydantic предлагает, вы можете использовать классы данных вместе с dataclass-wizard для этой же задачи. Это немного проще, поскольку вам не нужно определять сопоставление для ключей в оболочке lisp, таких как server-time .

Простой пример ниже:

 from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime

from dataclass_wizard import fromdict


@dataclass
class Something:
    data: Data
    # or simply:
    #   server_time: str
    server_time: datetime


@dataclass
class Data:
    id: int
    ks: dict[str, int]
    items: list[Person]


@dataclass
class Person:
    id: int
    name: str
    surname: str


# note: data is defined in the OP above
input_data = ...

print(fromdict(Something, input_data))
 

Вывод:

 Something(data=Data(id=81, ks={'k1': 25, 'k2': 5}, items=[Person(id=1, name='John', surname='Smith'), Person(id=2, name='Jane', surname='Doe')]), server_time=datetime.datetime(2021, 12, 9, 14, 18, 40))
 

Комментарии:

1. Так input_data точно соответствует первому JSON, который я определил в своем вопросе? Чтобы получить JSON из объекта Something и наоборот, должны ли мы использовать asdict() и fromdict() соответственно?

2. @LJG Да, это правильно, input_data должно соответствовать JSON сверху. Я отметил, что ваши данные JSON в этом случае могут быть определены просто как dict объект. Чтобы получить строку JSON, если таково намерение, вам нужно будет вызвать json.dumps asdict результат, однако, если это более удобно, вы можете создать подкласс из класса JSONWizard mixin, как указано в документах, а затем можете просто использовать to_json() метод для прямого преобразования экземпляра в строку JSON.

Ответ №2:

Я вижу, что вы указали fastapi и pydantic, поэтому я бы посоветовал вам следовать официальному руководству, чтобы узнать, как работает fastapi. Здесь у вас есть целая часть, объясняющая использование pydantic с fastapi.


чтобы точнее ответить на ваш вопрос, модели pydantic хорошо объясняются в документе.

простой пример:

 from typing import List
from pydantic import BaseModel

class Data(BaseModel):
    id: int
    ks: str
    items: List[str]

class Something(BaseModel):
    data: Data
    # you can replace it by a pydantic time type that fit your need
    server_time: str = Field(alias="server-time")
 

Ответ №3:

Я рекомендую ознакомиться с официальным руководством для более подробного рассмотрения того, как фреймворк обрабатывает создание и проверку модели данных с помощью pydantic.

Чтобы ответить на ваш вопрос:

 from datetime import datetime
from typing import List
from pydantic import BaseModel


class K(BaseModel):
    k1: int
    k2: int


class Item(BaseModel):
    id: int
    name: str
    surname: str


class DataModel(BaseModel):
    id: int = -1
    ks: K = None
    items: List[Item] = []
    server_time: datetime = datetime.now()

 

Ответ №4:

 from pydantic import BaseModel

class User(BaseModel):
    id: int
    name = "Jane Doe"
 

Комментарии:

1. Вопрос не задавался для какой -либо модели Pydantic. В вопросе был конкретный пример ввода, для которого требовались вложенные модели Pydantic.