Can't define __table_args__ on a child-class in a single-table inheritance setup

513 views
Skip to first unread message

Andrew Pashkin

unread,
May 7, 2017, 10:41:43 AM5/7/17
to sqlalchemy
I've found that if __table_args__ is present on a child class in a single-table inheritance setup, SQLAlchemy throws sqlalchemy.exc.ArgumentError: Can't place __table_args__ on an inherited class with no table. At the same time it is possible to define a column with index=True on a child class, which alters the parent table the same way as __table_args__.

Here is my setup:

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))

And it throws:

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.

Do somebody know any workarounds? 

mike bayer

unread,
May 8, 2017, 4:01:40 PM5/8/17
to sqlal...@googlegroups.com
there's a long term issue to provide some compatibility here at
https://bitbucket.org/zzzeek/sqlalchemy/issues/2700/support-__table_args__-on-single-inh.
For things like Index you can create those out of the table like this:

class Whatever(...):
..

Index('my_index', Whatever.some_column)


for UniqueConstraint, CheckConstraint, these also will "auto attach" in
modern versions if you create them in terms of the columns:

UniqueConstraint(Whatever.some_column)

If you use string names, you can append it:

uq = UniqueConstraint("some_column")
Whatever.__table__.append_constraint(uq)



On 05/07/2017 10:41 AM, Andrew Pashkin wrote:
> I've found that if __table_args__ is present on a child class in a
> single-table inheritance setup
> <http://docs.sqlalchemy.org/en/latest/orm/inheritance.html#single-table-inheritance>,
> SQLAlchemy throws sqlalchemy.exc.ArgumentError: Can't place
> __table_args__ on an inherited class with no table. At the same time it
> is possible to define a column with index=Trueon a child class, which
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> You received this message because you are subscribed to the Google
> Groups "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to sqlalchemy+...@googlegroups.com
> <mailto:sqlalchemy+...@googlegroups.com>.
> To post to this group, send email to sqlal...@googlegroups.com
> <mailto:sqlal...@googlegroups.com>.
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

Andrew Pashkin

unread,
May 8, 2017, 4:33:19 PM5/8/17
to sqlalchemy
Awesome, thank you for the response, this is what I was looking for.

Reply all
Reply to author
Forward
0 new messages