Зефир сериализуется вложенным с родительским полем

Извините, если об этом уже спрашивали, я не смог найти решение или аналогичный вопрос (возможно, используя неправильные слова).

Я обновляю существующий API Flask, который получает данные от клиента, которого мы не контролируем (не можем изменить формат данных JSON), используя marshmallow и peewee.

Формат данных выглядит следующим образом:

{
    "site_id": "0102931",
    "update_date": "2018/02/11-09:33:23",
    "updated_by": "chan1",
    "crc": "a82131cf232ff120aaf00001293f",
    "data": [{"num": 1,
              "id": "09213/12312/1",
              "chain": "chain2",
              "operator": "0000122",
              "op_name": "Fred",
              "oid": "12092109300293"
             },
             {"num": 2,
              "id": "09213/12312/2",
              "chain": "chain1",
              "operator": "0000021",
              "op_name": "Melissa",
              "oid": "8883390393"
             }]           
}

Нас не интересует ничего в основном блоке, кроме site_id, который должен копироваться в каждый из объектов в списке при десериализации для создания моделей и хранения данных.

Это модель в peeewee:

class production_item(db.Model):
   site_id = TextField(null=False)
   id_prod = TextField(null=False)
   num = SmallIntegerField(null=False)
   chain = TextField(null=False)
   operator = TextField(null=False)
   operator_name = TextField(null=True)
   order_id = TextField(null=False)

А это схема маршмеллоу:

class prodItemSchema(Schema):
    num=String(required=True)
    id=String(required=True)
    chain=String(required=True)
    operator=String(required=True)
    op_name=String(required=False, allow_none=True)
    oid=String(required=False, allow_none=True)

Я не могу найти способ передать идентификатор сайта из основной структуры с помощью метода load() и декораторов предварительной загрузки/пост-загрузки для prodItemSchema, поэтому модель не может быть создана. Кроме того, я хотел бы, чтобы зефир проверял всю структуру для меня, а не делал две части между ресурсом и схемой, как они делают в коде прямо сейчас.

Но не могу найти в документации способ сделать что-то подобное, возможно ли это?


person Alberto    schedule 27.03.2018    source источник
comment
Я не верю, что есть способ сделать это только с одной схемой. Вероятно, вам нужны две схемы, одна для основного объекта и одна для «данных», и делать то, что вам нужно, в перехватчиках до или после загрузки внутри схемы для основной объект.   -  person PoP    schedule 28.03.2018
comment
Я попробовал вложенную схему, но не смог найти способ получить значение site_id из родительской схемы, поэтому я остановился на альтернативном способе. Я автоматически отвечу на свой вопрос с помощью кода, возможно, это лучший способ, но этот работает.   -  person Alberto    schedule 03.04.2018


Ответы (1)


В marshmallow можно передавать значения из родительской схемы в дочерние перед сериализацией с помощью pre_dump в родительской схеме для установки контекст. Как только контекст установлен, функциональное поле может использоваться для получения значения от родителя.

class Parent(Schema):
    id = fields.String(required=True)
    data = fields.Nested('Child', many=True)

    @pre_dump
    def set_context(self, parent, **kwargs):
        self.context['site_id'] = parent['id']
        return data

class Child(Schema):
    site_id = fields.Function(inherit_from_parent)

def inherit_from_parent(child, context):
    child['site_id'] = context['site_id']
    return child
person infosmith    schedule 25.11.2019
comment
о, круто, я не знал, что вы можете использовать контекст таким образом! - person Alberto; 25.11.2019