我有一个SyncEntities类(如下所示)。
我有几个与SyncEntities类相关的其他类(例如下面显示的CommodityTypes)。
我的所有Base子类都有此列uuidKey = Column(String, primary_key=True)
假设se是SyncEntities的一个实例。 se.entityKind是Base子类的名称。
如何查询se.uuidKey的se.entityKind类过滤中的对象?
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
答案 0 :(得分:2)
此处的结构与“多态关联”类似,但不完全相同,您可以在此博客文章中了解此模式:http://techspot.zzzeek.org/2007/05/29/polymorphic-associations-with-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()
这里有一个mixin也可以使用backref:
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)