Reputation: 103
I have a model in database to store global app setting. Settings can be with different type, so I've made a data_type ad discriminator with polymorphic identities.
class MiscSetting(db.Model):
__tablename__ = "settings_misc"
__table_args__ = (db.UniqueConstraint("county", "name", name="uc_county_name"),)
id = db.Column(db.Integer, primary_key=True)
county = db.Column(db.String, nullable=True)
name = db.Column(db.String(length=50))
data_type = db.Column(db.String(50))
__mapper_args__ = {
'polymorphic_on': data_type,
'with_polymorphic': '*'
}
class StringSetting(MiscSetting):
__tablename__ = 'settings_string'
id = db.Column(db.Integer, db.ForeignKey('settings_misc.id'), primary_key=True)
value = db.Column(db.String)
__mapper_args__ = {
'polymorphic_identity': 'string'
}
class IntegerSetting(MiscSetting):
__tablename__ = 'settings_integer'
id = db.Column(db.Integer, db.ForeignKey('settings_misc.id'), primary_key=True)
value = db.Column(db.Integer)
__mapper_args__ = {
'polymorphic_identity': 'integer'
}
When I try to dump all objects I received, not "value" found.
settings = db.session.query(MiscSetting).all()
dump = json.dumps(MiscSettingSchema().dump(settings, many=True))
class MiscSettingSchema(BaseSchema):
class Meta:
model = MiscSetting
The question is how to include value into Marshmallow Schema?
Upvotes: 1
Views: 568
Reputation: 764
I'm not using marshmallow-sqlalchemy but I just ran into polymorphic relationships in plain marshmallow and here's how I solved the problem using a custom field.
from marshmallow import Schema
from marshmallow.fields import (
String,
Field,
)
from marshmallow.exceptions import ValidationError
class ClassA(Schema):
attribute_1 = String(default='Hello Polymorphic Relationships!')
attribute_2 = String(default='Hello Polymorphic Relationships!')
class ClassB(Schema):
attribute_3 = String(default='Hello Polymorphic Associations!')
attribute_4 = String(default='Hello Polymorphic Associations!')
class PolymorphicRelationship(Field):
def __init__(self, *args, nested=(), **kwargs):
super().__init__(*args, **kwargs)
self.CLASSES = nested
def _serialize(self, value, attr, obj, **kwargs):
for nested_class in self.CLASSES:
try:
return nested_class().dump(value)
except ValidationError:
continue
raise ValidationError(f'Unable to validate with: {self.CLASSES}')
def _deserialize(self, value, attr, data, **kwargs):
for nested_class in self.CLASSES:
try:
return nested_class().load(value)
except ValidationError:
continue
raise ValidationError(f'Unable to validate with: {self.CLASSES}')
class ClassC(Schema):
data_type = PolymorphicRelationship(nested=(ClassA, ClassB))
def main():
schema_a = ClassA()
schema_b = ClassB()
schema_c = ClassC()
a = schema_a.load({'attribute_1': 'foo'})
b = schema_b.load({'attribute_3': 'bar'})
c = schema_c.load({'data_type': {'attribute_3': 'foo'}})
d = schema_c.load({'data_type': {'attribute_4': 'bar'}})
print('a', schema_a.dump(a))
print('b', schema_a.dump(b))
print('c', c)
print('d', d)
if __name__ == '__main__':
main()
Upvotes: 1