【问题标题】:Marshmallow ModelSchema to Mapping Class Inheritance SqlAlchemyMarshmallow ModelSchema 到映射类继承 SqlAlchemy
【发布时间】:2020-01-21 14:24:24
【问题描述】:

我遇到了这个问题,我使用 ModelSchema 来验证我的 API 输入,这给了我一个数据库模型,它工作正常,但是如果我使用映射类继承(单表类型),ModelSchema 只给我没有父级子属性。

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)

当我使用 SerialInterfaceForm().load(input_json) 它返回 <SerialInterface (transient 1477443543280)> ,使用 __dict__: {'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x00000157FE7F6550>, 'type': 'RS485', 'transmission_rate': 9600, 'mad_id': 1, 'serial_protocol': <SerialProtocol (transient 1477443544120)>} 我的疑问是如何让 Marshmallow ModelSchema 返回正确的孩子及其属性

【问题讨论】:

    标签: python flask sqlalchemy flask-sqlalchemy flask-marshmallow


    【解决方案1】:

    找到解决办法,覆盖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
    

    【讨论】:

      猜你喜欢
      • 2021-07-12
      • 1970-01-01
      • 2012-03-20
      • 2015-07-01
      • 2015-05-23
      • 1970-01-01
      • 2017-12-07
      • 2011-11-22
      • 2010-11-25
      相关资源
      最近更新 更多