Столбцы таблицы сопоставления SQLAlchemy с фильтрами
У меня есть таблица в PostgreSQL, которая включает в себя информацию о документах. Скажем так:
table: doc
id (int)
name (string)
type (int)
тип - категория для документа (например, 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)
Это, очевидно, не работает, потому что у нас нет объекта запроса здесь.
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
, Это имеет больше смысла как иерархия.