2017-05-07 11 views
1

単一テーブル継承設定の子クラスに__table_args__がある場合、SQLAlchemyはsqlalchemy.exc.ArgumentError: Can't place __table_args__ on an inherited class with no tableをスローします。同時に、子クラスにindex=Trueという列を定義することができます。この場合、親テーブルは__table_args__と同じ方法で変更されます。ここで単一テーブル継承の設定で子クラスに__table_args__を定義できません

は私の設定です:

import sqlalchemy as sa 
import sqlalchemy.ext.declarative 

from sqlalchemy.ext.declarative import declarative_base 


Base = declarative_base() 


class A(Base): 
    __tablename__ = 'a' 

    id = sa.Column(sa.Integer, primary_key=True) 
    type = sa.Column(sa.Text, nullable=False) 

    __mapper_args__ = { 
     'polymorphic_on': type, 
    } 


class B(A): 
    b = sa.Column(sa.Integer, index=True) 

    __mapper_args__ = { 
     'polymorphic_identity': 'b', 
    } 


class C(A): 
    c = sa.Column(sa.Integer) 

    __mapper_args__ = { 
     'polymorphic_identity': 'c', 
    } 

    __table_args__ = (
     sa.Index('ix_test', c), 
    ) 


engine = sa.engine.create_engine("sqlite://", echo=True) 
Base.metadata.create_all(engine) 
session = sa.orm.Session(engine) 

session.add_all([ 
    B() 
]) 

session.commit() 

print(session.query(A)) 

そして、それはスロー:

Traceback (most recent call last): 
File "test.py", line 29, in <module> 
    class C(A): 
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla 
rative/api.py", line 64, in __init__ 
    _as_declarative(cls, classname, cls.__dict__) 
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla 
rative/base.py", line 88, in _as_declarative 
    _MapperConfig.setup_mapping(cls, classname, dict_) 
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla 
rative/base.py", line 103, in setup_mapping 
    cfg_cls(cls_, classname, dict_) 
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla 
rative/base.py", line 133, in __init__ 
    self._setup_inheritance() 
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla 
rative/base.py", line 442, in _setup_inheritance 
    "Can't place __table_args__ on an inherited class " 
sqlalchemy.exc.ArgumentError: Can't place __table_args__ on an inherited class with no table. 

誰かが回避策を知っていますか?

答えて

2

インデックスをテーブル定義の外に配置することができます。

class C(A): 
    c = sa.Column(sa.Integer) 

    __mapper_args__ = { 
     'polymorphic_identity': 'c', 
    } 

Index('ix_test', C.c) 
+0

これは良い回避策です。 'CheckConstraint'のような他の制約でも動作します。どうもありがとうございました。それは私のために多くの時間を節約しました。 –

+0

STIサブクラスのコンポジット・ユニーク制約を作成したいときにうまく機能します。この場合、列は '@ declared_attr'でも後でマップされます。どうもありがとう! – itsjef

0

SQLAlchemy 2.3にアップデートした後、このエラーが発生しました。最後に、これは__table_args__ = {'extend_existing': True}で私のために発生した

、 -

あなたがテーブルの引数を削除することができれば、それは2つのサブクラスが共通で、フィールド名を共有する場合は特に、動作します(ただし、他の事に文句を言うことがあります。この問題を回避するには、たとえばように、明示的にサブクラスのテーブル名を指定することでした:

class Establishment(Model): 
    __tablename__ = 'establishments' 
    name = Column(String(32)) 

class Cafe(Establishment): 
    __mapper_args__ = {'polymorphic_identity': 'cafe'} 
    coffee_type = Column(String(32)) 

class Bar(Establishment): 
    __tablename__ = 'establishments' 
    __table_args__ = {'extend_existing': True} 
    __mapper_args__ = {'polymorphic_identity': 'bar'} 
    alcohol_license_number = Column(String(40)) 
    bar_type = Column(Enum(BarType)) # defined elsewhere 

class Restaurant(Establishment): 
    __tablename__ = 'establishments' 
    __table_args__ = {'extend_existing': True} 
    __mapper_args__ = {'polymorphic_identity': 'bar'} 
    alcohol_license_number = Column(String(40)) 
    cuisine_list = Column(String(255)) 

ラフ例が、うまくいけば、アイデアは理にかなっている - レストランとそのアルコールのライセンス情報を保持するフィールドを持っているので、我々が望むの両方をバーこれらの2つは、競合ではなくテーブルの既存のフィールドを使用するようになりました。 SQLAlchemy 2.3以降のtablenameを指定します。

私はこの例が質問(Indexesについてのもの)とまったく同じ問題ではないことを知っていますが、同じエラーが発生するため、この解決策もこの場合と同様に機能するはずです。

関連する問題