Я реализовал наследование объединенной таблицы, как описано в вопросе Наследование SQLAlchemy .
Существует следующая ситуация: Я хотел бы иметь
- Пользователь , который имеет
emailaddress
- Псевдоним , который присваивает псевдоним -
emailaddress
другому адресу электронной почты
Чтобы сохранитьemailaddress
уникально, идея заключается в том, чтобы оба класса наследовали от Emailaddress
, используя наследование объединенной таблицы .В примерах реализованы следующие классы:
Emailaddress
EmailaddressUser(Emailaddress)
EmailaddressAlias(Emailaddress)
Наследование позволяетследующее использование:
u = EmailaddressUser(name="Testuser", emailaddress="testuser@test.com")
=> Мне не нужно создавать экземпляр Emailaddress
заранее - это облегчает использование.
К сожалению, то же самое не работает для EmailaddressAlias
, хотя единственное отличие - это второй атрибут ForeignKey с тем же атрибутом emailaddress
.Поэтому мне нужно указать attribute_concept .НО:
a = EmailaddressAlias (
real_emailaddress="testuser@test.com",
alias_emailaddress="tu@test.com"
)
-> Выдает ошибку IntegrityError при добавлении его в базу данных.Смотрите полный пример здесь:
import sqlalchemy as sa
import sqlalchemy.orm as orm
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Emailaddress(Base):
__tablename__ = 'emailaddresses'
emailaddress = sa.Column(sa.String, primary_key=True)
emailtype = sa.Column(sa.String, nullable=False)
__mapper_args__ = {'polymorphic_on': emailtype}
class EmailaddressUser(Emailaddress):
__tablename__ = 'emailaddress_users'
__mapper_args__ = {'polymorphic_identity': 'user'}
emailaddress = sa.Column(
sa.String,
sa.ForeignKey('emailaddresses.emailaddress'),
primary_key=True)
name = sa.Column(sa.String, nullable=False)
class EmailaddressAlias(Emailaddress):
__tablename__ = 'emailaddresses_alias'
alias_emailaddress = sa.Column(
sa.String,
sa.ForeignKey('emailaddresses.emailaddress'),
primary_key=True)
real_emailaddress = sa.Column(
sa.ForeignKey('emailaddresses.emailaddress'),
nullable=False)
__mapper_args__ = {
'polymorphic_identity': 'alias',
'inherit_condition':Emailaddress.emailaddress==alias_emailaddress}
if __name__ == '__main__':
engine = sa.create_engine ('sqlite:///email.sqlite', echo=True)
Base.metadata.bind = engine
Base.metadata.create_all ()
Session = orm.sessionmaker (engine)
session = Session ()
# add user (works):
u = EmailaddressUser(name="Testuser", emailaddress="testuser@test.com")
session.add(u)
session.commit()
# --> INSERT INTO emailaddresses (emailaddress, emailtype) VALUES (?, ?)
# --> ('testuser@test.com', 'user')
# 'emailaddress' is inserted correctly
# add alias (throws an IntegrityError):
a = EmailaddressAlias (
real_emailaddress="testuser@test.com",
alias_emailaddress="tu@test.com"
)
session.add(a)
session.commit()
# --> INSERT INTO emailaddresses (emailtype) VALUES (?)' ('alias',)
# 'emailaddress' is missing! => IntegrityError