Проблема
Как группировать поля при сериализации плоско структурированного объекта SQLAlchemy с помощью Marshmallow без изменения плоской структуры данных в фоновом режиме?
Пример
Предположим, что a Модель SQLAlchemy в приложении Flask выглядит следующим образом:
from app import db # db using SQLAlchemy
class Data(db.Model):
x = db.Column(db.Float(), required=True)
y = db.Column(db.Float(), required=True)
d = db.Column(db.Float())
Как я могу сериализовать этот объект, чтобы x
и y
были вложены в coordinates
, сохраняя при этом плоскую структуру данных в фон (модель)? Вывод должен выглядеть примерно так:
{
"coordinates": {
"x": 10.56
"y": 1
},
"d": 42.0
}
Проблема возникает именно потому, что я использую схему Data
с опцией many=True
. Инициализация примерно такая:
schema_data = MomentData()
schema_datas = MomentData(many=True)
Кандидаты в решение
Так что это то, что я пробовал до сих пор, но ни один из них не сработал.
Создание второй схемы
Добавление второй схемы и изменение схемы Data
по сравнению с предыдущим дает:
class CoordinatesSchema(Schema):
x = fields.Float(required=True)
y = fields.Float(required=True)
class DataSchema(Schema):
coordinates = fields.Nested(coordinatesSchema, required=True)
d = fields.Float()
Наличие этого на месте поднимает проблему необходимости go через каждый Data
и добавляем вручную схему Coordinates
. Мои данные поступают из запроса SQLAlchemy, возвращающего список Data
объектов, так что я могу легко вывести их, используя schema_datas
.
Используя fields.Dict
С Marshmallows fields
Модуль предлагает словарь, я тоже пробовал.
def DataSchema(Schema):
coordinates = fields.Dict(keys=fields.String(),
value=fields.Float(),
required=True,
default={
"x": Data.x,
"y": Data.y
})
d = fields.Float()
Кажется, тоже не работает, потому что Зефир не может автоматически найти Data.x
и Data.y
при использовании schema_datas.dump()
.
Использование самостоятельного размещения
Наиболее логичным путем решения будет самовложение. Но (из того, что я понял, прочитав документацию ), само вложенность относится только к вложению одного или нескольких других экземпляров в объекте. Я хочу вложить тот же экземпляр.
class DataSchema(Schema):
x = fields.Float(required=True, load_only=True)
y = fields.Float(required=True, load_only=True)
coordinates = fields.Nested(
lambda: DataSchema(only=('x', 'y')),
dump_only=True)
Но, к сожалению, это тоже не сработало.
Использование Decorator @pre_dump
Inspired эта проблема на странице Github Marshmallow , я попытался использовать декоратор @pre_dump
для достижения желаемого результата, но снова не удалось.
class CoordinatesSchema(Schema):
x = fields.Float(required=True)
y = fields.Float(required=True)
class DataSchema(Schema):
coordinates = fields.Nested(coordinatesSchema, required=True)
d = fields.Float()
@pre_dump
def group_coordinates(self, data, many):
return {
"coordinates": {
"x": data.x,
"y": data.y
},
"d": data.d
}
Но я не могу понять, как чтобы сделать это правильно ...
Итак, мой вопрос, что я делаю не так и как я могу решить эту проблему?