具有额外数​​据的SQLAlchemy通用关联

时间:2019-05-24 16:14:25

标签: python sqlalchemy

我正在尝试建立类似于此示例的通用关联:

https://docs.sqlalchemy.org/en/13/_modules/examples/generic_associations/table_per_association.html

我想向关联中添加额外的数据,并且让孩子多态

这是我要实现的设置:

我有两个不同的应用程序,都在一个表中显示数据。用户能够自定义他们在两个表中看到的列。每个用户都与一个站点相关联。如果他们没有设置自定义设置,则他们看到的表列将默认为其网站的表列。列的排序应在关联内部完成,以便可以根据用户/站点进行自定义。

我能够为两种不同类型的列设置多态身份,以及用户,站点和列之间的通用m2m关系。

问题是我无法从每个关系中获取“常规”属性。我的目标是做这样的事情:

user = session.query(User).first()
user.cols[0].ordinal = 1

site = session.query(Site).first()
site.cols[0].ordinal = 1

我知道要实现这一点,我必须转储关联对象的关联表,但是我似乎无法弄清楚在保持关联通用性的情况下如何轻松做到这一点。

Base = declarative_base()


class Col(Base):
    __tablename__ = 'cols'
    id            = Column(Integer, primary_key=True)
    label         = Column(String(30))
    type          = Column(String(20))

    __mapper_args__ = {
        'polymorphic_identity':'cols',
        'polymorphic_on':type,
        'with_polymorphic': '*'
    }


class OrderCol(Col):
    __tablename__ = 'order_cols'
    id = Column(Integer, ForeignKey('cols.id'), primary_key=True)
    __mapper_args__ = {
        'polymorphic_identity':'order',
        'polymorphic_load': 'inline'
    }



class ItemCol(Col):
    __tablename__ = 'item_cols'
    id = Column(Integer, ForeignKey('cols.id'), primary_key=True)
    __mapper_args__ = {
        'polymorphic_identity':'item',
        'polymorphic_load': 'inline'
    }


class HasCols:
    @declared_attr
    def col_association(cls):
        return Table(
            f"{cls.__tablename__}_cols",
            cls.metadata,
            Column("col_id", ForeignKey("cols.id"), primary_key=True),
            Column(f"{cls.__tablename__}_id", ForeignKey(f"{cls.__tablename__}.id"), primary_key=True),
            Column('ordinal', Integer) # I need to be able to access this property
        )

    @declared_attr
    def cols(cls):
        return relationship(Col, secondary=cls.col_association)

    @declared_attr
    def order_cols(cls):
        return relationship(OrderCol, secondary=cls.col_association)

    @declared_attr
    def item_cols(cls):
        return relationship(ItemCol, secondary=cls.col_association)


class Site(HasCols, Base):
    __tablename__ = 'sites'
    id = Column(Integer, primary_key=True)
    name = Column(String(100))


class User(HasCols, Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(100))

0 个答案:

没有答案