Python 尽管存在棘手的ForeignKey关系,SQLAlchemy类如何正确继承?

Python 尽管存在棘手的ForeignKey关系,SQLAlchemy类如何正确继承?,python,inheritance,sqlalchemy,Python,Inheritance,Sqlalchemy,我实现了问题中描述的联接表继承 有以下情况:我想有一个 用户具有电子邮件地址 别名将别名-电子邮件地址分配给另一个电子邮件地址 为了保持emailaddress的唯一性,可以使用联接表继承让这两个类从emailaddress继承。这些示例实现了以下类: 电子邮件地址 EmailaddressUser(Emailaddress) EmailaddressAlias(Emailaddress) 继承支持以下用法: u = EmailaddressUser(name="Testuser", e

我实现了问题中描述的联接表继承

有以下情况:我想有一个

  • 用户具有
    电子邮件地址
  • 别名将别名-
    电子邮件地址
    分配给另一个电子邮件地址
为了保持
emailaddress
的唯一性,可以使用联接表继承让这两个类从
emailaddress
继承。这些示例实现了以下类:

  • 电子邮件地址
  • EmailaddressUser(Emailaddress)
  • EmailaddressAlias(Emailaddress)
继承支持以下用法:

u = EmailaddressUser(name="Testuser", emailaddress="testuser@test.com")
=>我不需要预先实例化
电子邮件地址
,这便于使用


不幸的是,同样的事情不适用于
EmailaddressAlias
,尽管唯一的区别是第二个属性,它是同一属性
emailaddress
的外键。因此,我需要指定inherit_条件。但是:

-->将IntegrityError添加到数据库时引发该错误。请参见此处的完整示例:

将sqlalchemy作为sa导入
将sqlalchemy.orm导入为orm
从sqlalchemy.ext.declarative导入声明性基础
Base=声明性_Base()
类电子邮件地址(基):
__tablename_uu='emailaddresses'
emailaddress=sa.Column(sa.String,主键=True)
emailtype=sa.Column(sa.String,null=False)
__mapper_args_uu={'polymorphic_on':emailtype}
类EmailaddressUser(Emailaddress):
__tablename\uuuu='emailaddress\u用户'
__mapper_args_uu={'polymorphic_identity':'user'}
emailaddress=sa.Column(
sa.字符串,
sa.ForeignKey('EmailAddresss.emailaddress'),
主(主键=真)
name=sa.Column(sa.String,null=False)
类EmailaddressAlias(Emailaddress):
__tablename_uuu='emailaddresses_uAlias'
别名\u emailaddress=sa.Column(
sa.字符串,
sa.ForeignKey('EmailAddresss.emailaddress'),
主(主键=真)
real\u emailaddress=sa.Column(
sa.ForeignKey('EmailAddresss.emailaddress'),
可空=假)
__映射器参数={
“多态性_标识”:“别名”,
“继承条件”:Emailaddress.Emailaddress==别名\u Emailaddress}
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
engine=sa.create_engine('sqlite:///email.sqlite,echo=True)
Base.metadata.bind=引擎
Base.metadata.create_all()
Session=orm.sessionmaker(引擎)
会话=会话()
#添加用户(作品):
u=EmailaddressUser(name=“Testuser”,emailaddress=”testuser@test.com")
会话.添加(u)
session.commit()
#-->在emailaddresses(emailaddress,emailtype)中插入值(?,)
# --> ('testuser@test.com“,”用户“)
#“emailaddress”已正确插入
#添加别名(抛出IntegrityError):
a=电子邮件地址别名(
real_电子邮件地址=”testuser@test.com",
别名\u电子邮件地址=”tu@test.com"
)
会议.添加(a)
session.commit()
#-->在emailaddresses(emailtype)中插入值(?)('alias',)
#“emailaddress”丢失!=>完整性反射镜

似乎有一个问题,EmailaddressAlias是从EmailAddress继承的,而不是从Base继承的

我不是这方面的专家,也没有通过mapper_args完成这项工作,但我发现使用设置外键非常有效。例如:

from sqlalchemy.orm import relationship
class EmailaddressAlias(Base):
...
    alias_emailaddress_fk = sa.Column(sa.String, sa.ForeignKey('emailaddresses.emailaddress'))
    alias_emailaddress = relationship(EmailAddress, primaryjoin=alias_emaladdress_fk==EmailAddress.emailaddress)
    real_emailaddress_fk = sa.Column(sa.String, ForeignKey('emailaddresses.emailaddress'))
    real_emailaddress = relationship(EmailAddress,primaryjoin=real_emailaddress_fk==EmailAddress.emailaddress)

EmailaddressAlias
有4个属性,包括从
emailaddress
继承的
emailaddress
name
,这些属性不会传递给新对象的构造函数。因此,这里应该有例外。我认为从
Emailaddress
继承
EmailaddressAlias
是一个错误。试着描述一下你想得到更好的帮助的意图。为了澄清我的意图,我添加了一些词语。关于您的评论:
名称
不是从
电子邮件地址
继承的。它只是
EmailaddressUser
中的一个属性。经过一些测试,我认为它是SQLAlchemy中的一个缺陷,原因如下:在
EmailaddressAlias
中重命名:
alias\u emailaddress
emailaddress
(也在at
inherit\u condition
中)解决了这个问题。但是,
inherit\u条件
应该允许不同的命名!这是zzzeek写的一篇好文章:-非常感谢!
from sqlalchemy.orm import relationship
class EmailaddressAlias(Base):
...
    alias_emailaddress_fk = sa.Column(sa.String, sa.ForeignKey('emailaddresses.emailaddress'))
    alias_emailaddress = relationship(EmailAddress, primaryjoin=alias_emaladdress_fk==EmailAddress.emailaddress)
    real_emailaddress_fk = sa.Column(sa.String, ForeignKey('emailaddresses.emailaddress'))
    real_emailaddress = relationship(EmailAddress,primaryjoin=real_emailaddress_fk==EmailAddress.emailaddress)