外键约束中引用的Flask SQLAlchemy列“id”不存在

时间:2018-04-01 01:48:52

标签: python postgresql flask sqlalchemy flask-sqlalchemy

最小例子:

models.py

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Patient(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    notes = db.relationship("Note", backref=db.backref("patient", lazy=True))

class Note(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    patient_id = db.Column(db.Integer, db.ForeignKey("patient.id"), nullable=False)

app.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.secret_key = "super secret"

POSTGRES = {
    "user": "postgres",
    "pw": "password",
    "db": "test_db",
    "host": "localhost",
    "port": "5432",
}
app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql://%(user)s:%(pw)s@%(host)s:%(port)s/%(db)s" % POSTGRES
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["DEBUG"] = True

from models import db
with app.app_context():
    db.init_app(app)

run.py

from app import app, db

if __name__ == "__main__":
    with app.app_context():
        db.create_all()
    app.run()

但是,我收到以下错误:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) column "id" referenced in foreign key constraint does not exist
 [SQL: '\nCREATE TABLE note (\n\tid SERIAL NOT NULL, \n\tpatient_id INTEGER NOT NULL, \n\tPRIMARY KEY (id), \n\tFOREIGN KEY(patient_id) REFERENCES patient (id)\n)\n\n'] (Background on this error at: http://sqlalche.me/e/f405)

当我在psql控制台中使用外键定义表时,它似乎有效。出了什么问题?

1 个答案:

答案 0 :(得分:0)

我尝试了您的示例代码(我必须将应用初始化添加到 app.py ,以便您的代码按原样运行)。它按预期工作,并创建了notepatient表。

这告诉我你的问题是环保的。我愿意打赌,如果你在Postgres实例中创建了一个全新的测试数据库并运行了你的示例代码,它也适用于你。

因此,让我们关注您要连接的数据库的状态。

您获得的ProgrammingError例外显示来自Postgres本身的错误。它说它无法创建notes表,因为没有patient.id这样的外键。这可能会让您失望,因为您知道 patient.id中定义了models.py密钥。不幸的是,我没有从您发布的内容中获得足够的信息给您一个明确的答案,但我猜是这样的:

Postgres中的patient表可能已经从之前的运行中创建,但具有不同的模式(例如,可能首先定义时没有id列)。 create_all()函数将创建目标数据库中不存在的表,但不会使用修改后的模式更新现有表。

去检查你的Postgres数据库并查看patient表。它是否实际上有一个id列被正确定义为主键?

如果您需要这些表格中没有数据,请尝试删除它们并再次运行您的应用程序。我的猜测是它会正确创建两个表并且不会抛出任何错误。