Я пытаюсь десериализовать глубокую структуру с помощью зефира.Например:
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')
Обновление:
Я думаю, что происходит то, что зефир не пытается десериализовать объект HoursDay
, когда пытается десериализовать диктат new_practitioner_at_location
.Если я уберу поведение backpopulates
из поля HoursDay.hour
, вы увидите, что оно просто присвоило этой структуре несериализованную структуру данных.Для меня это не имеет никакого смысла, тем более что это работает, когда вы просто десериализуете диктат hour
напрямую, а не внедряете его в new_practitioner_at_location
.Любая помощь будет оценена.