this is addressed in the docs which discuss "cascading" here: https://docs.sqlalchemy.org/en/14/orm/declarative_mixins.html#mixing-in-columns-in-inheritance-scenarios
"The `declared_attr.cascading` feature currently does *not* allow for a subclass to override the attribute with a different function or value. This is a current limitation in the mechanics of how `@declared_attr` is resolved, and a warning is emitted if this condition is detected. This limitation does *not* exist for the special attribute names such as `__tablename__`, which resolve in a different way internally than that of `declared_attr.cascading`." you will see a warning in your program's output: SAWarning: Attribute 'record_id' on class <class '__main__.Programmer'> cannot be processed due to @declared_attr.cascading; skipping as a workaround, you can look for the attribute in __dict__ and return it, though you still get the warning: class has_polymorphic_id(object): @declared_attr.cascading def record_id(cls): if "record_id" in cls.__dict__: return cls.__dict__['record_id'] elif has_inherited_table(cls): return Column(ForeignKey("employee.record_id"), primary_key=True) else: return Column(Integer, primary_key=True) otherwise you'd want to look at "cls" with inspect(cls).local_table etc. and figure out the correct column to include in the FK if you are doing things this way. On Sun, Nov 28, 2021, at 4:22 PM, niuji...@gmail.com wrote: > I've just manually put this line to the `Programmer` class definition, but it > still gives me the same error, strangely: > > > class Programmer(Engineer): > __tablename__ = 'programmer' > record_id = Column(ForeignKey('engineer.record_id'), > primary_key=True) > .... > On Sunday, November 28, 2021 at 8:25:30 AM UTC-8 Mike Bayer wrote: >> >> >> On Sun, Nov 28, 2021, at 4:24 AM, niuji...@gmail.com wrote: >>> I'm using the "joined table inheritance" model. I have three levels of >>> inheritance. >>> >>> class has_polymorphic_id(object): >>> @declared_attr.cascading >>> def record_id(cls): >>> if has_inherited_table(cls): >>> return Column(ForeignKey('employee.record_id'), >>> primary_key=True) >>> else: >>> return Column(Integer, primary_key=True) >>> >>> >>> class Employee(has_polymorphic_id, Base): >>> __tablename__ = 'employee' >>> name = Column(String(50)) >>> type = Column(String(50)) >>> >>> __mapper_args__ = { >>> 'polymorphic_identity':'employee', >>> 'polymorphic_on':type >>> } >>> >>> class Engineer(Employee): >>> __tablename__ = 'engineer' >>> .... >>> >>> class Programmer(Engineer): >>> __tablename__ = 'programmer' >>> .... >>> >>> This only works for the second level, namely `Enginner` can inherits the >>> foreignkey/primarykey from `Employee`'s mixin, but the next level, the >>> `Programmer`, python gives me an error: >>> `sqlalchemy.exc.NoForeignKeysError: Can't find any foreign key >>> relationships between 'engineer' and 'programmer'.` >> >> The "cascading" attribute seems to be working correctly. The error here is >> because you aren't providing any column that will allow for a JOIN between >> the "programmer" and "engineer" table. >> >> you would want Programmer.record_id to be a foreign key to >> Engineer.record_id, not Employee.record_id. When you load Programmer >> rows, the join would be "FROM employee JOIN engineer ON <onclause> JOIN >> programmer ON <onclause>". >> >> >>> >>> Is this designed this way? And if I manually set the foreignkey, should the >>> third level reference to the base level or to its immediate parent level's >>> primarykey? >> >> it has to be to the immediate parent. that's what the error message here is >> talking about. >> >> >> >>> >>> >>> -- >>> 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. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/sqlalchemy/02ce8134-2946-4d1b-b6d3-e47ad7944e0en%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/sqlalchemy/02ce8134-2946-4d1b-b6d3-e47ad7944e0en%40googlegroups.com?utm_medium=email&utm_source=footer>. >> > > > -- > 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+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/sqlalchemy/b08ba9e6-e1e3-451e-b39b-bc5ee4b63847n%40googlegroups.com > > <https://groups.google.com/d/msgid/sqlalchemy/b08ba9e6-e1e3-451e-b39b-bc5ee4b63847n%40googlegroups.com?utm_medium=email&utm_source=footer>. -- 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+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/4b018f98-3848-4ed9-8172-2c373ad1ca46%40www.fastmail.com.