无法为映射表组装任何主键列

时间:2014-07-21 18:53:15

标签: python sqlalchemy flask-sqlalchemy flask-migrate

当我尝试创建数据库架构迁移时,我得到了这个奇怪的错误。你能帮我弄清楚是什么错了吗?

$ python app.py db upgrade
[skipped]
sqlalchemy.exc.ArgumentError: Mapper Mapper|EssayStateAssociations|essay_associations could not assemble any primary key columns for mapped table 'essay_associations'

我的模特:

class EssayStateAssociations(db.Model):
    __tablename__ = 'essay_associations'

    application_essay_id = db.Column(
        db.Integer,
        db.ForeignKey("application_essay.id"),
        primary_key=True),
    theme_essay_id = db.Column(
        db.Integer,
        db.ForeignKey("theme_essay.id"),
        primary_key=True),
    state = db.Column(db.String, default="pending")

4 个答案:

答案 0 :(得分:29)

表中不能有两个主键。相反,您必须使用复合主键。 这可以通过在模型中添加PrimaryKeyConstraint来完成,如下所示(请记住在__table_args__中关闭括号之前添加逗号:

from db import PrimaryKeyConstraint

class EssayStateAssociations(db.Model):
    __tablename__ = 'essay_associations'
    __table_args__ = (
        PrimaryKeyConstraint('application_essay_id', 'theme_essay_id'),
    )

    application_essay_id = db.Column(
        db.Integer,
        db.ForeignKey("application_essay.id"))
    theme_essay_id = db.Column(
        db.Integer,
        db.ForeignKey("theme_essay.id"))
    state = db.Column(db.String, default="pending")

答案 1 :(得分:22)

您收到此错误是因为您的Column()定义后面有逗号,这导致application_essay_idtheme_essay_id每个都被解析为包含{{1}的单元素元组而不仅仅是Column。这会阻止SQLAlchemy“看到”列存在,从而导致模型不包含任何主键列。

如果您只是替换

Column

application_essay_id = db.Column(
    db.Integer,
    db.ForeignKey("application_essay.id"),
    primary_key=True),
theme_essay_id = db.Column(
    db.Integer,
    db.ForeignKey("theme_essay.id"),
    primary_key=True),

然后你的错误将被修复。

除此之外:因为SQLAlchemy(以及Alembic和Flask-SQLAlchemy)包含一些声明模型/表的语法,这些语法/表涉及将逗号分隔的application_essay_id = db.Column( db.Integer, db.ForeignKey("application_essay.id"), primary_key=True) theme_essay_id = db.Column( db.Integer, db.ForeignKey("theme_essay.id"), primary_key=True) s序列作为参数传递(例如传递给Column或者op.create_table()构造函数)和其他涉及声明具有Table() s作为类属性的类的其他人,通过剪切和粘贴Column声明来解决此错误非常容易从第一个语法到第二个,忘记删除一些逗号。我怀疑这个容易犯的错误是这个问题有如此多的观点的原因 - 当我发布这个答案时超过16000个。

答案 2 :(得分:0)

由于语法错误,我收到了此错误。 I.v我的声明中拼错了“ primary_key”

答案 3 :(得分:0)

在关系数据库表中,它必须要求候选键。您可以参考本文https://en.wikipedia.org/wiki/Candidate_key

您只需要添加主键或复合主键。对于复合主键,可以在Flask APP中使用以下行。无需导入任何东西。一切都会通过Flask中的 db 变量来解决。

在您的示例中,

db.PrimaryKeyConstraint(application_essay_id , application_essay_id )