Как переименовать атрибут в сериализторах pydantic?

Есть подобная модель:

from pydantic import BaseModel


class SomeModel(BaseModel):
    attr1: str
    attr2: str
    attr3: str

Мне необходимо на выходе получить:

{ attr_1: "someText", attr_2: "someText", attr_3: "someText" }

Я знаю, что в marshmallow есть для этого параметр attribute, есть ли что-то подобное в pydantic?

Пробовал alias, но, кажется, это другое.


Ответы (1 шт):

Автор решения: insolor

Именно через alias. Пример:

from pydantic import BaseModel, Field


class SomeModel(BaseModel):
    attr1: str = Field(alias="attr_1")
    attr2: str = Field(alias="attr_2")
    attr3: str = Field(alias="attr_3")
    
    class Config:
        allow_population_by_field_name = True


some_model = SomeModel(attr1="someText", attr2="someText", attr3="someText")
print(some_model)  # attr1='someText' attr2='someText' attr3='someText'
print(some_model.json(by_alias=True))  # {"attr_1": "someText", "attr_2": "someText", "attr_3": "someText"}

Вывод:

attr1='someText' attr2='someText' attr3='someText'
{"attr_1": "someText", "attr_2": "someText", "attr_3": "someText"}

Настройка allow_population_by_field_name = True тут используется, чтобы при создании объекта SomeModel(attr1="someText", attr2="someText", attr3="someText") можно было указывать внутренние имена атрибутов (по умолчанию при наличии псевдонима при создании объекта нужно указывать псевдонимы атрибутов).

Также, чтобы создавать псевдонимы автоматически, в Config можно указать функцию преобразования имен в псевдонимы, пример:

import re


def alias_generator(name: str):
    return '_'.join(re.search(r"([a-zA-Z]+)(\d+)", name).groups())


class SomeModel(BaseModel):
    attr1: str
    attr2: str
    attr3: str
    
    class Config:
        alias_generator = alias_generator
        allow_population_by_field_name = True


some_model = SomeModel(attr1="someText", attr2="someText", attr3="someText")
print(some_model)
print(some_model.json(by_alias=True))

Можно также использовать готовый пакет pyhumps, который умеет преобразовывать snake_case в camelCase или PascalCase и обратно (но правда не умеет преобразовывать attr1 в attr_1, поэтому в предыдущем примере пришлось писать свою функцию). Пример:

import humps


class SomeModel(BaseModel):
    attr_one: str
    attr_two: str
    attr_three: str
    
    class Config:
        alias_generator = humps.camelize
        allow_population_by_field_name = True


some_model = SomeModel(attr_one="someText", attr_two="someText", attr_three="someText")
print(some_model)
print(some_model.json(by_alias=True))

Вывод:

attr_one='someText' attr_two='someText' attr_three='someText'
{"attrOne": "someText", "attrTwo": "someText", "attrThree": "someText"}`

Полезная статья: CamelCase Models with FastAPI and Pydantic

→ Ссылка