首页 > 解决方案 > 在多态标识中包含棉花糖模式中的子字段

问题描述

我在数据库中有一个模型来存储全局应用程序设置。设置可以有不同的类型,所以我制作了一个具有多态身份的 data_type 广告鉴别器。

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'
}

当我尝试转储我收到的所有对象时,没有找到“价值”。

settings = db.session.query(MiscSetting).all()
dump = json.dumps(MiscSettingSchema().dump(settings, many=True))

class MiscSettingSchema(BaseSchema):
class Meta:
    model = MiscSetting

问题是如何将价值包含到棉花糖模式中?

标签: sqlalchemypolymorphic-associationsmarshmallowmarshmallow-sqlalchemy

解决方案


我没有使用 marshmallow-sqlalchemy,但我只是在纯 marshmallow 中遇到了多态关系,这就是我使用自定义字段解决问题的方法。

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()

推荐阅读