I'm having an issue where SQLAlchemy throws a NoForeignKeysError when it attempts to determine the primary join for two tables. The odd thing is this issue only occurs on the second instantiation of the models (i.e. if I drop the tables and recreate them it works the first time I run the script but not the subsequent times). Even odder is if I use inspect
to view the ForeignKeys of the child tables I can clearly see that they exist (psql
and just looking at the declarative base's metadata confirms this as well). My models are generated by a script and all other tables with similar or more complex relations work as expected however it is only this particular set of tables that has this issue.
The specific errors it throws are:
sqlalchemy.exc.NoForeignKeysError: Can't find any foreign key relationships between 'task_statuses' and 'task_data'.
and
sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on relationship task_statuses.task_data - there are no foreign keys linking these tables. Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.
Code snippet:
class TaskData(db_base):
__tablename__ = 'task_data'
__table_args__ = ({'extend_existing' : True})
id = Column(Integer, primary_key=True)
tags = relationship('TaskTags', backref='task_data', cascade='all, delete-orphan', passive_deletes=True)
statuses = relationship('TaskStatuses', backref='task_data', cascade='all, delete-orphan', passive_deletes=True)
class TaskTags(db_base):
__tablename__ = 'task_tags'
__table_args__ = ({'extend_existing' : True})
id = Column(Integer, primary_key=True)
taskdata_id = Column(Integer, ForeignKey('task_data.id', ondelete='CASCADE'))
class TagStatuses(db_base):
__tablename__ = 'task_statuses'
__table_args__ = ({'extend_existing' : True})
id = Column(Integer, primary_key=True)
taskdata_id = Column(Integer, ForeignKey('task_data.id', ondelete='CASCADE'))
Update:
After rereading the error message, I've realized that SQLAlchemy seems to think that task_statuses
is the parent table when in fact it's the child. That still explains nothing and is actually more confusing but may be noteworthy. Even if a primaryjoin is specified the error persists.
The problem ended up being with Graphene-SQLAlchemy
For whatever reason, defining the SQLAlchemy model and the Graphene-SQLAlchemy equivalent in the same file was causing SQLAlchemy to have some unexpected behavior.
I resolved the issue by placing the models in a different file then generating the required Graphene-SQLAlchemy objects in the original file