嵌套结构时 Marshmallow 反序列化失败

Marshmallow deserializing fails when structure is nested

我正在尝试用棉花糖反序列化深层结构。例如:

hour = {
    'day': {
        'name': 'monday'
    }
}
loaded_hour, error = HoursSerializationSchema().load(hour) # this works

new_practitioner_at_location = {
    'hours': [
        hour
    ]
}
loaded, error = PractitionerToServiceLocationSerializationSchema().load(new_practitioner_at_location) # this fails

当我尝试反序列化 new_practitioner_at_location 时,我得到以下信息(在序列化程序处理 'day' 键时发生):

AttributeError: 'dict' object has no attribute '_sa_instance_state'

请注意,当该结构未嵌套在 new_practitioner_at_location 内时,相同的模式用于反序列化相同的数据结构(小时)。

显示问题的独立脚本:

from sqlalchemy import Column, Integer, ForeignKey, String
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate

base = declarative_base()


class HoursDay(base):
    __tablename__ = 'HoursDay'
    uid = Column(Integer, primary_key=True)

    name = Column(String)

    hour_id = Column(Integer, ForeignKey('Hours.uid'))
    hour = relationship("Hours", back_populates="day")

    def __init__(self, **kwargs):
        super().__init__(**kwargs)


class Hours(base):
    __tablename__ = 'Hours'
    uid = Column(Integer, primary_key=True)

    practitioner_at_location_id = Column(Integer, ForeignKey('PractitionerToServiceLocation.uid'))
    practitioner_at_location = relationship('PractitionerToServiceLocation', back_populates="hours")

    day = relationship(HoursDay, uselist=False, back_populates="hour")

    def __repr__(self):
        return f'<Hours {self.uid}>'


class PractitionerToServiceLocation(base):
    """
    A practitioner practices at a number of service locations.
    """
    __tablename__ = 'PractitionerToServiceLocation'
    uid = Column(Integer, primary_key=True)

    hours = relationship("Hours", back_populates="practitioner_at_location")

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def __repr__(self):
        return f'<PractitionerToServiceLocation {self.uid}>'


app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
db = SQLAlchemy(app, model_class=base)
ma = Marshmallow(app)
migrate = Migrate(app, db)

from marshmallow import fields


class HoursDaySerializationSchema(ma.ModelSchema):
    class Meta:
        model = HoursDay


class HoursSerializationSchema(ma.ModelSchema):
    class Meta:
        model = Hours

    day = fields.Nested(HoursDaySerializationSchema)


class PractitionerToServiceLocationSerializationSchema(ma.ModelSchema):
    class Meta:
        model = PractitionerToServiceLocation

        hours = fields.Nested('HoursSerializationSchema', many=True)


if __name__ == "__main__":
    hour = {
        'day': {
            'name': 'monday'
        }
    }
    loaded_hour, error = HoursSerializationSchema().load(hour) # this works

    new_practitioner_at_location = {
        'hours': [
            hour
        ]
    }
    loaded, error = PractitionerToServiceLocationSerializationSchema().load(new_practitioner_at_location) # this fails
    print('hi')

更新:

我认为发生的事情是棉花糖在尝试反序列化 new_practitioner_at_location 字典时没有尝试反序列化 HoursDay 对象。如果我从 HoursDay.hour 字段中删除 backpopulates 行为,那么您可以看到它只是将未序列化的数据结构分配给该字段。这对我来说毫无意义,特别是因为当你直接反序列化 hour 字典而不是将它嵌入 new_practitioner_at_location 中时它会起作用。 任何帮助,将不胜感激。

这是一个简单的类似拼写错误的错误:

class PractitionerToServiceLocationSerializationSchema(ma.ModelSchema):
    class Meta:
        model = PractitionerToServiceLocation

        hours = fields.Nested('HoursSerializationSchema', many=True)

您正在 class Meta 内定义 hours,但它需要在您的模式本身中:

class PractitionerToServiceLocationSerializationSchema(ma.ModelSchema):
    class Meta:
        model = PractitionerToServiceLocation

    hours = fields.Nested('HoursSerializationSchema', many=True)