There are quite a few posts on this error but none of the answers apply to me, as far as I can see my code already conforms to the answers in the other posts.
I import my complete model and it has all classes, columns and relationships defined. In my code on the very first statement I execute I get this error:
InvalidRequestError: When initializing mapper mapped class Application->application, expression 'Version' failed to locate a name ("name 'Version' is not defined"). If this is a class name, consider adding this relationship() to the class after both dependent classes have been defined.
Interestingly the first statement I execute that "triggers" the error does not even involve the classes in the message. For the record it is user_mk = User.query.filter_by(user_name='mk').first()
.
The part of the model that errors is a simple 1-M relationship.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
...etc...
app = Flask(__name__)
app.config.from_object(TestConfig)
db = SQLAlchemy(app)
class User(UserMixin, db.Model)
__bind_key__ = 'app'
__tablename__ = 'user'
...etc...
class Version(db.Model):
__bind_key__ = 'app'
__tablename__ = 'version'
version_id = db.Column(db.Integer, primary_key=True)
version_number = db.Column(db.Integer, nullable=False)
release_number = db.Column(db.Integer, nullable=False)
modification_number = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
test_status = db.Column(db.Integer, index=True)
lifecycle = db.Column(db.Text, index=True, server_default=db.text("\"Current\""))
timestamp = db.Column(db.DateTime, server_default=db.text("CURRENT_TIMESTAMP"))
notes = db.Column(db.Text)
class Application(db.Model):
__bind_key__ = 'app'
__tablename__ = 'application'
application_id = db.Column(db.Integer, primary_key=True)
application_name = db.Column(db.Text)
version_id = db.Column(db.ForeignKey('version.version_id'), index=True)
description = db.Column(db.Text)
notes = db.Column(db.Text)
version = db.relationship('Version')
I cannot understand how SQLAlchemy cannot "see" the Version
class from the Application
class. What am I Doing wrong?
UPDATE Following the suggestion in the answer below a different error occurs.
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'mapped class Version->version'. Original exception was: Could not determine join condition between parent/child tables on relationship Version.applications - there are no foreign keys linking these tables. Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.
The code I tried is
class Version(db.Model):
__bind_key__ = 'app'
__tablename__ = 'version'
version_id = db.Column(db.Integer, primary_key=True)
version_number = db.Column(db.Integer, nullable=False)
release_number = db.Column(db.Integer, nullable=False)
modification_number = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
test_status = db.Column(db.Integer, index=True)
lifecycle = db.Column(db.Text, index=True, server_default=db.text("\"Current\""))
timestamp = db.Column(db.DateTime, server_default=db.text("CURRENT_TIMESTAMP"))
notes = db.Column(db.Text)
applications = db.relationship('Application',
backref='version',
primaryjoin='Version.version_id == Application.version_id',
)
class Application(db.Model):
__bind_key__ = 'app'
__tablename__ = 'application'
application_id = db.Column(db.Integer, primary_key=True)
application_name = db.Column(db.Text)
version_id = db.Column(db.ForeignKey('version.version_id'), index=True)
description = db.Column(db.Text)
notes = db.Column(db.Text)
ANSWER
Thanks @djnz. The answer that works is as follows, but it is not clear why. Observe that the primaryjoin
clause under Version
has been replaced with a foreign_keys
clause.
class Version(db.Model):
__bind_key__ = 'app'
__tablename__ = 'version'
version_id = db.Column(db.Integer, primary_key=True)
version_number = db.Column(db.Integer, nullable=False)
release_number = db.Column(db.Integer, nullable=False)
modification_number = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
test_status = db.Column(db.Integer, index=True)
lifecycle = db.Column(db.Text, index=True, server_default=db.text("\"Current\""))
timestamp = db.Column(db.DateTime, server_default=db.text("CURRENT_TIMESTAMP"))
notes = db.Column(db.Text)
applications = db.relationship('Application',
backref='version',
foreign_keys="Application.version_id",
)
class Application(db.Model):
__bind_key__ = 'app'
__tablename__ = 'application'
application_id = db.Column(db.Integer, primary_key=True)
application_name = db.Column(db.Text)
version_id = db.Column(db.ForeignKey('version.version_id'), index=True)
description = db.Column(db.Text)
notes = db.Column(db.Text)
db
instance? Have you made sure that all models get imported/defined before first use? – Ilja Everilä