質問SQLAlchemy Inheritanceに記載されているように、結合テーブルの継承を実装しました。トリッキーなForeignKey関係を持っていても、SQLAlchemyクラスは適切に継承できますか?
次のような状況があります:私は、エイリアスを割り当てemailaddress
- ユーザー持っていると思います - 別のメールアドレス
emailaddress
をemailaddress
をユニークにするには、両方のクラスをから継承させることが考えられますを使用してテーブルの継承を継承。
Emailaddress
EmailaddressUser(Emailaddress)
EmailaddressAlias(Emailaddress)
継承は以下の使用可能になります:例は以下のクラスを実装
u = EmailaddressUser(name="Testuser", emailaddress="[email protected]")
を=>私はする必要はありませんEmailaddress
beforehをインスタンス化する使用を容易にする。
残念ながら、EmailaddressAlias
では同じことが動作しませんが、唯一の違いは同じ属性のForeignKeyである2番目の属性emailaddress
です。したがって、inherit_conditionを指定する必要があります。 BUT:
a = EmailaddressAlias (
real_emailaddress="[email protected]",
alias_emailaddress="[email protected]"
)
- >データベースに追加するときにIntegrityErrorをスローします。ここでは、完全な例を参照してください:問題はEmailaddressAliasは基地からのEmailAddressから継承していないということがあるかもしれないよう
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="[email protected]")
session.add(u)
session.commit()
# --> INSERT INTO emailaddresses (emailaddress, emailtype) VALUES (?, ?)
# --> ('[email protected]', 'user')
# 'emailaddress' is inserted correctly
# add alias (throws an IntegrityError):
a = EmailaddressAlias (
real_emailaddress="[email protected]",
alias_emailaddress="[email protected]"
)
session.add(a)
session.commit()
# --> INSERT INTO emailaddresses (emailtype) VALUES (?)' ('alias',)
# 'emailaddress' is missing! => IntegrityError
'EmailaddressAlias'は、新しいオブジェクトのコンストラクタに渡さないでくださいemailaddress'とEmailaddress'、'から継承された '' NAME'含む4つの特性を有します。したがってここでは例外が予想されます。私は 'Emailaddress'から' EmailaddressAlias'の継承が間違いであると信じています。より良い助けを得るためのあなたの意図を記述してください。 –
私の意図を明確にするためにいくつかの単語を追加しました。あなたのコメントをconcen: 'name'は' Emailaddress'から継承されません。 'EmailaddressUser'の属性です。 –
テストの結果、SQLAlchemyのバグだと思う: 'EmailaddressAlias':' alias_emailaddress'から 'emailaddress'への名前変更(' inherit_condition'内でも)は問題を解決します。しかし、 'inherit_condition'は異なる命名を許すべきです! –