SQLAlchemyAutoSchema 嵌套反序列化
SQLAlchemyAutoSchema Nested Deserialization
我有以下内容:
Models.py
class Policy(db.Model):
policy_id = db.Column(db.Integer, primary_key=True)
client_reference = db.Column(db.String(50), nullable=False)
submission_id = db.Column(db.ForeignKey('submission.submission_id'), nullable=False)
submission = relationship("Submission", back_populates="policies", lazy='joined')
class Submission(db.Model):
submission_id = db.Column(db.Integer, primary_key=True)
client_reference = db.Column(db.String(50), nullable=False)
policies = db.relationship('Policy', back_populates='submission', lazy='joined')
Schema.py
class PolicySchema(SQLAlchemyAutoSchema):
class Meta:
model = Policy
include_relationships = True
load_instance = True
unknown = INCLUDE
exclude = ("submission",)
submission_id = auto_field("submission")
class SubmissionSchema(SQLAlchemyAutoSchema):
class Meta:
model = Submission
include_relationships = False
load_instance = True
policies = fields.Nested(PolicySchema, many=True, allow_none=True)
routes.py
@submission_api.route('/submission/', methods=['POST'])
def add_new():
body = request.get_json()
validated_request = SubmissionSchema().load(body, session=db.session)
db.session.add(validated_request)
db.session.commit()
return jsonify({"submission_id": validated_request.submission_id}), 200
如果我尝试使用以下方式将新记录添加到提交中:
{
"client_reference": "POL1",
"description": "hello"
}
它工作正常。
如果我打电话给:
{
"client_reference": "POL1","description": "hello",
"policies": [{"client_reference": "A1"}]
}
我收到这个错误:
File "/usr/local/lib/python3.8/site-packages/marshmallow_sqlalchemy/schema/load_instance_mixin.py", line 89, in load
raise ValueError("Deserialization requires a session")
ValueError: Deserialization requires a session
我不明白为什么。我以相同的方式为两者传递会话(其相同的功能)。我已经进行了更改以导致此问题,因为它正在运行(提醒更频繁地提交代码)。
恐怕没有真正的解决方案,只是在此 github issue. To quote TMiguelIT:
中讨论的解决方法
Would it not be reasonable for us to create our own Nested field that inherits from the original Marshmallow Nested, allowing us to pass the session object down? Would this diminish usability in any way?
据我了解,解决方案应如下所示:
from marshmallow import fields
class Nested(fields.Nested):
"""Nested field that inherits the session from its parent."""
def _deserialize(self, *args, **kwargs):
if hasattr(self.schema, "session"):
self.schema.session = db.session # overwrite session here
self.schema.transient = self.root.transient
return super()._deserialize(*args, **kwargs)
因此您在 schemy.py
的顶部创建了自己的 Nested
字段(我刚刚从 marshmallow-sqlalchemy 复制了代码)并覆盖了会话。
我有以下内容:
Models.py
class Policy(db.Model):
policy_id = db.Column(db.Integer, primary_key=True)
client_reference = db.Column(db.String(50), nullable=False)
submission_id = db.Column(db.ForeignKey('submission.submission_id'), nullable=False)
submission = relationship("Submission", back_populates="policies", lazy='joined')
class Submission(db.Model):
submission_id = db.Column(db.Integer, primary_key=True)
client_reference = db.Column(db.String(50), nullable=False)
policies = db.relationship('Policy', back_populates='submission', lazy='joined')
Schema.py
class PolicySchema(SQLAlchemyAutoSchema):
class Meta:
model = Policy
include_relationships = True
load_instance = True
unknown = INCLUDE
exclude = ("submission",)
submission_id = auto_field("submission")
class SubmissionSchema(SQLAlchemyAutoSchema):
class Meta:
model = Submission
include_relationships = False
load_instance = True
policies = fields.Nested(PolicySchema, many=True, allow_none=True)
routes.py
@submission_api.route('/submission/', methods=['POST'])
def add_new():
body = request.get_json()
validated_request = SubmissionSchema().load(body, session=db.session)
db.session.add(validated_request)
db.session.commit()
return jsonify({"submission_id": validated_request.submission_id}), 200
如果我尝试使用以下方式将新记录添加到提交中:
{
"client_reference": "POL1",
"description": "hello"
}
它工作正常。
如果我打电话给:
{
"client_reference": "POL1","description": "hello",
"policies": [{"client_reference": "A1"}]
}
我收到这个错误:
File "/usr/local/lib/python3.8/site-packages/marshmallow_sqlalchemy/schema/load_instance_mixin.py", line 89, in load
raise ValueError("Deserialization requires a session")
ValueError: Deserialization requires a session
我不明白为什么。我以相同的方式为两者传递会话(其相同的功能)。我已经进行了更改以导致此问题,因为它正在运行(提醒更频繁地提交代码)。
恐怕没有真正的解决方案,只是在此 github issue. To quote TMiguelIT:
中讨论的解决方法Would it not be reasonable for us to create our own Nested field that inherits from the original Marshmallow Nested, allowing us to pass the session object down? Would this diminish usability in any way?
据我了解,解决方案应如下所示:
from marshmallow import fields
class Nested(fields.Nested):
"""Nested field that inherits the session from its parent."""
def _deserialize(self, *args, **kwargs):
if hasattr(self.schema, "session"):
self.schema.session = db.session # overwrite session here
self.schema.transient = self.root.transient
return super()._deserialize(*args, **kwargs)
因此您在 schemy.py
的顶部创建了自己的 Nested
字段(我刚刚从 marshmallow-sqlalchemy 复制了代码)并覆盖了会话。