Столбцы таблицы сопоставления SQLAlchemy с фильтрами

У меня есть таблица в PostgreSQL, содержащая информацию о документах. Скажем что-то вроде этого:

table: doc

id (int)
name (string)
type (int)

type – категория документа (например, 1 – паспорт, 2 – страховка и т. д.). Также у меня есть разные таблицы с дополнительной информацией для каждого типа документов.

table: info

id (int)
doc_id (fk)
info (additional columns)

Я хочу иметь модель SQLAlchemy для работы с каждым типом документа, связанного с его дополнительной информацией, и иметь возможность управлять отображаемыми столбцами (для Flask-Admin, если это важно).

Теперь, чтобы объединить две таблицы в какую-то «модель», я использовал Сопоставление столбцов таблицы из документации SQLAlchemy (когда был только один тип документов):

class DocMapping(db.Model):

    __table__ = doc.__table__.join(info)
    __mapper_args__ = {
        'primary_key': [doc.__table__.c.id]
    }

Теперь возникает вопрос: как создать несколько классов, унаследованных от db.Model (DocPassportMapping, DocInsuranceMapping и т. д.) на основе столбца doc.type?

Что-то такое:

__table__ = doc.__table__.join(info).filter(doc.type)

Очевидно, это не работает, потому что здесь нет объекта query.


person Max    schedule 09.09.2016    source источник


Ответы (1)


Если я вас правильно понял, вы хотите иметь иерархия наследования на основе DocMapping с DocMapping.type в качестве полиморфного идентификатора. Поскольку вы не предоставили полный пример, вот несколько похожая структура. У него наверняка есть отличия, но он должен быть применим к вашему. При этом используется наследование одной таблицы поверх объединенное отображение.

Модели:

In [2]: class Doc(Base):
   ...:     id = Column(Integer, primary_key=True, autoincrement=True)
   ...:     name = Column(Unicode)
   ...:     type = Column(Integer, nullable=False)
   ...:     __tablename__ = 'doc'
   ...:     

In [3]: class Info(Base):
   ...:     __tablename__ = 'info'
   ...:     doc_id = Column(Integer, ForeignKey('doc.id'), primary_key=True)
   ...:     value = Column(Unicode)
   ...:     doc = relationship('Doc', backref=backref('info', uselist=False))
   ...:     

In [4]: class DocMapping(Base):
   ...:     __table__ = Doc.__table__.join(Info)
   ...:     __mapper_args__ = {
   ...:         'primary_key': (Doc.id, ),
   ...:         # These declare this mapping polymorphic
   ...:         'polymorphic_on': Doc.type,
   ...:         'polymorphic_identity': 0,
   ...:     }
   ...:     

In [5]: class Passport(DocMapping):
   ...:     __mapper_args__ = {
   ...:         'polymorphic_identity': 1,
   ...:     }
   ...:     

In [6]: class Insurance(DocMapping):
   ...:     __mapper_args__ = {
   ...:         'polymorphic_identity': 2,
   ...:     }
   ...:     

Тестирование:

In [7]: session.add(Insurance(name='Huono vakuutus',
   ...:                       value='0-vakuutus, mitään ei kata'))

In [8]: session.commit()

In [15]: session.query(DocMapping).all()
Out[15]: [<__main__.Insurance at 0x7fdc0a086400>]

In [16]: _[0].name, _[0].value
Out[16]: ('Huono vakuutus', '0-vakuutus, mitään ei kata')

Дело в том, что вам, вероятно, не нужны несколько классов, которые наследуются от db.Model в качестве базовых, а классы, которые наследуются от DocMapping. Это имеет гораздо больше смысла как иерархия.

person Ilja Everilä    schedule 09.09.2016