Зефир ModelSchema для отображения класса наследования SqlAlchemy - PullRequest
0 голосов
/ 21 января 2020

Я с этой проблемой, я использую ModelSchema для проверки моего ввода API, и это дает мне модель базы данных, она работает нормально, но если я использую наследование класса отображения (тип Single Table), 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 вернуть правильного потомка с его атрибутами

1 Ответ

0 голосов
/ 21 января 2020

Я нашел решение, переписал make_instance ModelSchema и вызвал __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
...