0

我有一个 SyncEntities 类(如下所示)。

我还有几个与 SyncEntities 类相关的其他类(例如 CommodityTypes 也在下面显示)。

我所有的 Base 子类都有这个专栏uuidKey = Column(String, primary_key=True)

假设 se 是 SyncEntities 的一个实例。se.entityKind 是 Base 子类的名称。

如何查询在 se.entityKind 类中筛选 se.uuidKey 的对象?

class SyncEntities(Base):
    __tablename__ = 'SyncEntities'

    uuidKey = Column(String, primary_key=True)
    dateCreated = Column(DateTime, index=True)
    dateModified = Column(DateTime, index=True)
    dateSynced = Column(DateTime, index=True)
    username = Column(String)
    entityKind = Column(String)
    deleted = Column(Boolean)

    def __init__(self, entity, security):
        self.uuidKey = newUUID()
        self.dateCreated = security.now
        self.dateModified = security.now
        self.dateSynced = security.then
        self.username = security.username
        self.entityKind = entity.__tablename__
        self.deleted = False

    def modified(self, security):
        self.dateModified = security.now
        self.username = security.username

class CommodityTypes(Base):
    __tablename__ = 'CommodityTypes'
    uuidKey = Column(String, ForeignKey('SyncEntities.uuidKey'), primary_key=True)
    myName = Column(String, unique = True)
    sortKey = Column(Integer, unique = True)

    mySyncEntity = relationship("SyncEntities")

    def __init__(self, security, myName, sortKey):
        self.syncEntity = SyncEntities(self, security)
        self.uuidKey = self.syncEntity.uuidKey
        self.myName = myName
        self.sortKey = sortKey
4

1 回答 1

2

这里的结构与“多态关联”相似,但并不完全相同,您可以在此博客文章中阅读有关此模式的信息:http: //techspot.zzzeek.org/2007/05/29/polymorphic-与 sqlalchemy/ 的关联。这是一篇旧文章,但http://techspot.zzzeek.org/files/2007/discriminator_on_association.py上的示例后来作为更新示例添加。

这种情况略有不同,因为像 CommodityTypes 这样的对象仅引用单个 SyncEntities,而不是通常的多态关联中的多个。SyncEntities 也只能引用单一类型的相关对象,因为您在本地有 entityKind。

我会注意到这种设计的一个潜在问题是,您可能在其他表中有一个 uuidKey 指向特定 SyncEntities 实例的行,但不是与“entityKind”匹配的类型。如果 CommodityTypes 和 SyncEntities 之间的关系实际上是一对一的,那会改变一切 - 这种模式实际上是简单的连接表继承,您可以使用http://docs.sqlalchemy.org/en/rel_0_7/中描述的模式orm/inheritance.html

您也没有目标和 SyncEntities 之间的反向引用,这通常是自动化这些查找样式的一种方式。但是您仍然可以使用查找类的 entityKind 类型来近似事物:

def lookup_related(se):
    types = {
        'commodity':CommodityTypes,
        'foobar':FooBarTypes
    }
    cls = types[se.entityKind]
    session = object_session(se)
    return session.query(cls).filter(cls.mySyncEntity==se).all()

这是一个也可以使用 backref 的 mixin:

class HasSyncEntity(object):
    entity_kind = None
    "subclasses need to populate this"

    @declared_attr
    def uuidKey(cls):
        return Column(String, ForeignKey("SyncEntities.uuidKey"), primary_key=True)

    @declared_attr
    def mySyncEntity(cls):
        return relationship("SyncEntities", backref="_%s_collection" % cls.entity_kind)

CommodityTypes 变为:

class CommodityTypes(HasSyncEntity, Base):
    entity_kind = "commodity"
    # ...

然后将这样的方法添加到 SyncEntities,它会查找适当的 backref,然后您就完成了:

def get_related(self):
    return getattr(self, "_%s_collection" % self.entityKind)
于 2012-05-03T18:05:29.277 回答