python - Marshmallow ModelSchema to Mapping Class Inheritance SqlAlchemy
问题描述
i am with this problem, i using ModelSchema to validade my API input and this give me a Database Model, it works fine, but if i use a Mapping Class Inheritance(Single Table type) the ModelSchema give me only the parent without the children attributes.
class SerialInterface(sql.Model):
type = sql.Column(sql.String(50))
polymorphic_identity = {
'polymorphic_identity': 'serial_interface',
'polymorphic_on': type,
}
id = sql.Column(types.Integer, primary_key=True)
transmission_rate = sql.Column(types.Integer)
mad_id = sql.Column(types.Integer, sql.ForeignKey('mad.id'))
serial_protocol = sql.relationship(SerialProtocol, uselist=False, cascade="all, delete-orphan")
class RS485(SerialInterface):
parity = sql.Column(EnumSmart(Parity))
data_bits = sql.Column(types.Integer)
stop_bits = sql.Column(types.Integer)
polymorphic_identity = SerialTypes.RS485.name
class SerialInterfaceForm(BaseSchema):
class Meta(BaseSchema.Meta):
model = SerialInterface
transmission_rate = Integer(required=True)
mad_id = Integer(required=True)
serial_protocol = Nested(SerialProtocolForm, required=True)
parity = EnumField(Parity, required=True)
data_bits = Integer(required=True)
stop_bits = Integer(required=True)
When i use SerialInterfaceForm().load(input_json)
it return <SerialInterface (transient 1477443543280)>
, using __dict__
: {'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x00000157FE7F6550>, 'type': 'RS485', 'transmission_rate': 9600, 'mad_id': 1, 'serial_protocol': <SerialProtocol (transient 1477443544120)>}
My doubt is how i can make the Marshmallow ModelSchema return the correct child with his attributes
解决方案
我找到了解决方案,覆盖了ModelSchema的make_instance,并调用__mapper__.polymorphic_map
了找到的子类
class BaseSchema(marshmallow.ModelSchema):
@post_load
def make_instance(self, data, **kwargs):
"""Deserialize data to an instance of the model. Update an existing row
if specified in `self.instance` or loaded by primary key(s) in the data;
else create a new row.
:param data: Data to deserialize.
"""
instance = self.instance or self.get_instance(data)
if instance is not None:
for key, value in iteritems(data):
setattr(instance, key, value)
return instance
print(self.opts.model)
# kwargs, association_attrs = self._split_model_kwargs_association(data)
try:
instance = self.opts.model.__mapper__.polymorphic_map[data['type']].class_(**kwargs)
except Exception:
instance = self.opts.model(**kwargs)
for attr, value in iteritems(data):
setattr(instance, attr, value)
return instance
class Meta:
sqla_session = sql.session
推荐阅读
- intersection-observer - 交叉点观察者未触发从其他页面链接到的部分
- python - 无法在 Raspbian 上安装 tensorflow-text
- java - @Order 在两个列表中具有不同的值
- html - 在 html 编码中使用外部 css
- azure-data-factory - 从 Azure 数据工厂执行 MySQL 过程
- c++ - 试图指向类构造函数中的对象(C++)
- postgresql - 如何在postgresql中将语句结果复制到本地
- typescript - 尝试使用 rollup 和 vueJs 3 构建 vue 组件库
- javascript - 检查 `App` 的渲染方法并调用了 21 个明显的帧
- raku - 无法将 if 语句分配给变量