【发布时间】:2017-08-30 18:46:56
【问题描述】:
我很难写出这个问题。它涉及一个可能复杂且不常见的用例。
我在一个项目中定义了几个 ORM 类,它们负责维护一个通用的数据库模式和核心功能。例如,假设这是model.email 模块。
from sqlalchemy import Column, Index, ForeignKey
from sqlalchemy import Boolean, Integer, Text
from . import Base
class CampaignDB(Base):
"""
Note: this basic database mapper class is expected to be extended.
When sub-classing, be mindful to override mappings to other extended classes.
"""
__tablename__ = 'campaigns'
audience_id = Column(Integer, ForeignKey("audiences.id"))
active = Column(Boolean)
name = Column(Text)
这些 ORM 类作为包导入到其他几个项目中。在某些情况下,这些 ORM 类被子类化以提供额外的功能。例如,这里的CampaignDB 类被子类化以提供在特定项目上下文中发送电子邮件的支持。
from model.email import CampaignDB
class Campaign(CampaignDB):
"""
Provides sending capability to the email campaign ORM class.
"""
def __init__(self, audience_id=None, active=None, name=None):
self.audience_id = audience_id
self.active = active
self.name = name
def send(self):
print("send emails to the audience")
现在我想使用 SQLAlchemy 的类继承层次结构将 CampaignDB 和子类 Campaign 类重构为多态基础。例如,我想让CampaignDB 成为EmailCampaignDB 和PushCampaignDB 的基类。然后我想在导入项目中分别扩展EmailCampaignDB 和PushCampaignDB,例如EmailCampaign 和PushCampaign。但是,我仍然希望能够查询 Campaign 并返回 EmailCampaign 和 PushCampaign 的实例。
我已多次尝试解决此问题,但遇到了问题。特别是,session.query(Campaign).all() 不返回任何结果,因为 SQLAlchemy 似乎不将其视为基类。生成的 SQL 有以下 WHERE 子句:WHERE email.campaigns.type IN (NULL)
这是我正在尝试的要点。
class CampaignDB(Base):
"""
Note: this basic database mapper class is expected to be extended.
When sub-classing, be mindful to override mappings to other extended classes.
"""
__tablename__ = 'campaigns'
audience_id = Column(Integer, ForeignKey("audiences.id"))
active = Column(Boolean)
name = Column(Text)
type = Column(String(16))
__mapper_args__ = {
'polymorphic_on': type
}
class EmailCampaignDB(CampaignBaseDB):
__mapper_args__ = {
'polymorphic_identity': 'email'
}
class PushCampaignDB(CampaignBaseDB):
__mapper_args__ = {
'polymorphic_identity': 'push'
}
def send(self):
print("send push notifications to the audience")
class Campaign(CampaignDB):
pass
class EmailCampaign(EmailCampaignDB):
def send(self):
print("send emails to the audience")
class PushCampaign(PushCampaignDB):
def send(self):
print("send push notifications to the audience")
这可能吗?在这种“打包的 ORM”上下文中是否有更好的方法来实现这一点?
【问题讨论】:
-
我认为this question 几乎是您的确切用例。
标签: python sqlalchemy