Python 基于Mixin列的SQLalchemy连接继承查询
我有一个声明性类结构,如下所示:Python 基于Mixin列的SQLalchemy连接继承查询,python,orm,sqlalchemy,Python,Orm,Sqlalchemy,我有一个声明性类结构,如下所示: class BaseClass(Base): Column A Column B class Mixin(object): Column C class ItemA(BaseClass): Column D class ItemB(Mixin, BaseClass): pass class ItemC(Mixin, BaseClass): Column E 是否有一种方法可以将与_
class BaseClass(Base):
Column A
Column B
class Mixin(object):
Column C
class ItemA(BaseClass):
Column D
class ItemB(Mixin, BaseClass):
pass
class ItemC(Mixin, BaseClass):
Column E
是否有一种方法可以将与_polymorphic
结合使用,这样我就可以基于列C
对所有项目进行查询,而不必明确知道我有什么项目
?基本上
mixin_poly = with_polymorphic(base = BaseClass, classes = MixinClass.__subclasses__())
让我们假设在导入时,在声明带有多态性的之前,MixinClass
的所有派生都已导入
编辑
注意,我省略了连接表继承的样板文件,但假设它的设置正确,这样做
poly_base = with_polymorphic(base = BaseClass, classes = '*')
session.query(poly_base).filter(BaseClass.a == value, ...)
按预期从基类
查询列。关键是能够以相同的方式查询继承Mixin
类的子类中的公共列
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import inspect
Base = declarative_base()
class BaseClass(Base):
__tablename__ = 'base'
id = Column(Integer, primary_key=True)
type = Column(String)
a = Column(Integer)
b = Column(Integer)
__mapper_args__ = {"polymorphic_on": type}
class Mixin(object):
c = Column(Integer)
class ItemA(BaseClass):
__tablename__ = 'a'
id = Column(ForeignKey('base.id'), primary_key=True)
d = Column(Integer)
__mapper_args__ = {"polymorphic_identity": 'a'}
class ItemB(Mixin, BaseClass):
__tablename__ = 'b'
id = Column(ForeignKey('base.id'), primary_key=True)
__mapper_args__ = {"polymorphic_identity": 'b'}
class ItemC(Mixin, BaseClass):
__tablename__ = 'c'
id = Column(ForeignKey('base.id'), primary_key=True)
e = Column(Integer)
__mapper_args__ = {"polymorphic_identity": 'c'}
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
def magic_w_poly(base):
insp = inspect(base)
w_poly = []
crit = []
for mapper in insp.self_and_descendants:
if "c" in mapper.c:
w_poly.append(mapper)
crit.append(mapper.c.c)
w_col_c = with_polymorphic(base, w_poly)
def comparator(value):
return or_(
crit_elem == value
for crit_elem in crit
)
return w_col_c, comparator
s = Session(e)
w_col, comp = magic_w_poly(BaseClass)
print s.query(w_col).filter(comp(35))
最后查询:
SELECT base.id AS base_id, base.type AS base_type, base.a AS base_a, base.b AS base_b, b.id AS b_id, b.c AS b_c, c.id AS c_id, c.c AS c_c, c.e AS c_e
FROM base LEFT OUTER JOIN b ON base.id = b.id LEFT OUTER JOIN c ON base.id = c.id
WHERE b.c = :c_1 OR c.c = :c_2
最后查询:
SELECT base.id AS base_id, base.type AS base_type, base.a AS base_a, base.b AS base_b, b.id AS b_id, b.c AS b_c, c.id AS c_id, c.c AS c_c, c.e AS c_e
FROM base LEFT OUTER JOIN b ON base.id = b.id LEFT OUTER JOIN c ON base.id = c.id
WHERE b.c = :c_1 OR c.c = :c_2
很抱歉,我遗漏了联接表继承的样板文件,我将编辑我的原始问题以澄清这一点。关键是不必在查询中显式调用子类,因为我在编码时不知道它们,只知道它们在导入时存在(即Base.metadata
将包含它们)with_polymogic
允许我对BaseClass
的子类执行此操作,但我还没有弄清楚如何让它查询来自mixin而非基类的那些子类的公共列。请仔细查看“magic_w_poly()”。没有明确调用Mixin的特定子类,它定位所有具有预期列“C”的子类。修改它以查找在mro或类似文件中有Mixin的类应该很容易。如果Mixin有任意的列,而不仅仅是“c”,那么需要做更多的工作来生成一个列属性的名称空间,这个名称空间可以进行比较,可能是用来构建的。Doh,我错过了代码的后半部分。StackOverflow的渲染器确实需要在您可以滚动时使其更加明显。mixin类可能有任意数量的列,但它们是提前知道的。下一次我在做这个项目的时候,我会尝试一下这段代码,如果成功了,我会接受答案。我包括了所有的样板文件,因为我必须实际运行这些示例以确保它们有效;)很抱歉,我遗漏了联接表继承的样板文件,我将编辑我的原始问题以澄清这一点。关键是不必在查询中显式调用子类,因为我在编码时不知道它们,只知道它们在导入时存在(即Base.metadata
将包含它们)with_polymogic
允许我对BaseClass
的子类执行此操作,但我还没有弄清楚如何让它查询来自mixin而非基类的那些子类的公共列。请仔细查看“magic_w_poly()”。没有明确调用Mixin的特定子类,它定位所有具有预期列“C”的子类。修改它以查找在mro或类似文件中有Mixin的类应该很容易。如果Mixin有任意的列,而不仅仅是“c”,那么需要做更多的工作来生成一个列属性的名称空间,这个名称空间可以进行比较,可能是用来构建的。Doh,我错过了代码的后半部分。StackOverflow的渲染器确实需要在您可以滚动时使其更加明显。mixin类可能有任意数量的列,但它们是提前知道的。下一次我在做这个项目的时候,我会尝试一下这段代码,如果成功了,我会接受答案。我包括了所有的样板文件,因为我必须实际运行这些示例以确保它们有效;)