SQLAlchemy Foreign Key Error: "Could not find table 'user' for announcement.creator_id"
Misbah bagaskara purwanto
Posted on November 26, 2024
Problem Description:
I'm encountering an error when running my Flask application. The error occurs when I try to log in, and it seems related to the Announcement
model's foreign key referencing the User
model. Here's the error traceback:
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'announcement.creator_id' could not find table 'user' with which to generate a foreign key to target column 'id'
Relevant Code:
Here are the models involved:
User Model:
class User(db.Model, UserMixin):
__bind_key__ = 'main' # Bind to 'main' database
__tablename__ = 'user'
metadata = metadata_main # Explicit metadata
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(128), nullable=False)
role = db.Column(db.String(20), nullable=False)
is_admin_field = db.Column(db.Boolean, default=False)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@property
def is_admin(self):
"""Return True if the user is an admin."""
return self.role == 'admin'
def get_role(self):
"""Return the role of the user."""
return self.role
def __repr__(self):
return f"User('{self.username}', '{self.email}', '{self.role}')"
Announcement Model:
class Announcement(db.Model):
__bind_key__ = 'main'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(150), nullable=False)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_by = db.Column(db.String(50), nullable=False)
# ForeignKeyConstraint ensures the reference to user.id in 'main' database
creator_id = db.Column(db.Integer, nullable=False)
__table_args__ = (
ForeignKeyConstraint(
['creator_id'],
['user.id'],
name='fk_creator_user_id',
ondelete='CASCADE'
),
)
def __repr__(self):
return f"<Announcement {self.title}>"
Where the Module Was Declared:
# school_hub/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_migrate import Migrate
# Initialize extensions
db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()
def create_app():
app = Flask(__name__)
# Configurations
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:Root1234!@localhost/school_hub'
app.config['SECRET_KEY'] = '8d8a72493996de3050b75e0737fecacf'
app.config['SQLALCHEMY_BINDS'] = {
'main': 'mysql+pymysql://root:Root1234!@localhost/main_db',
'teacher_db': 'mysql+pymysql://root:Root1234!@localhost/teacher_database',
'student_db': 'mysql+pymysql://root:Root1234!@localhost/student_database',
}
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Initialize extensions with the app
db.init_app(app)
login_manager.init_app(app)
migrate.init_app(app, db)
# Set up Flask-Login user loader
from .models import User # Import User model here to ensure it's loaded
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# Register Blueprint
from .routes import main
app.register_blueprint(main)
# Ensure app context is pushed before calling db.create_all()
with app.app_context():
# Create all tables for the 'main' database
db.create_all() # This will create tables for the default 'main' database
# Explicitly create tables for the 'teacher_db' and 'student_db'
from .models import Teacher, Student, User # Ensure models are imported
# Create tables for 'teacher_db'
Teacher.metadata.create_all(bind=db.get_engine(app, bind='teacher_db'))
# Create tables for 'student_db'
Student.metadata.create_all(bind=db.get_engine(app, bind='student_db'))
return app
My Environment:
- Flask: Latest version
- Flask-SQLAlchemy: Latest version
- SQLAlchemy: Latest version
- Python: Latest version
My Question:
Why is SQLAlchemy unable to find the user
table, even though the table name matches the foreign key reference? How can I resolve this error?
Additional Context:
I'm using Flask-Migrate for database migrations. The User
model is bound to the main database, and the Announcement
model references this table. The error occurs when SQLAlchemy tries to create the foreign key constraint, and it cannot find the user
table.
What Did I Try?
-
Ensuring Correct Database Binding:
- I’ve ensured both models explicitly set
__bind_key__ = 'main'
to associate them with the same database.
- I’ve ensured both models explicitly set
-
Ensuring Correct Foreign Key Reference:
- The
Announcement
model has a foreign key referencing theid
column of theUser
model:
creator_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
- The
- I verified that the
User
model is correctly bound to'main'
and theuser
table exists.
-
Database Initialization:
- I’ve ensured that tables are created in the correct order, with the
User
table being created before theAnnouncement
table due to the foreign key constraint.
- I’ve ensured that tables are created in the correct order, with the
-
Error Handling and Suggestions:
- I’ve checked that both the
User
andAnnouncement
models are correctly imported and initialized. - I’ve confirmed that the foreign key reference should work as both models are bound to the same database.
- I’ve checked that both the
-
Repeated Checks on Database Bind:
- I double-checked the bind for the
User
andAnnouncement
models, ensuring both are using'main'
as the bind key.
- I double-checked the bind for the
-
Potential Missing Table Issue:
- The error could happen if the
User
table isn’t visible to SQLAlchemy at the time of the foreign key creation, so I ensured that theUser
table exists and is properly created before running theAnnouncement
model migration.
- The error could happen if the
Posted on November 26, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 27, 2024