64

当我尝试创建数据库架构迁移时,我遇到了这个奇怪的错误。你能帮我找出问题所在吗?

$ 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

5 回答 5

69

你得到这个错误是因为你的Column()定义后面有逗号,这导致application_essay_idtheme_essay_id每个都被解析为一个包含 aColumn而不是仅仅 a的单元素元组Column。这会阻止 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),

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)包含一些用于声明模型/表的语法,这些语法涉及将逗号分隔的Columns 序列作为参数(例如 toop.create_table()Table()构造函数)传递,而其他语法则涉及将 s 声明Column为类属性,通过将声明从第一种语法剪切并粘贴到第二种语法并忘记删除一些逗号,很容易遇到此错误。Column我怀疑这个容易犯的错误是这个问题有如此大量观点的原因——在我发布这个答案时超过 16000。

于 2018-04-15T14:15:23.323 回答
44

一个表中不能有两个主键。相反,您必须使用复合主键。这可以通过PrimaryKeyConstraint在您的模型中添加 a 来完成,如下所示(请记住在关闭括号之前添加逗号__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")
于 2014-09-25T03:09:00.650 回答
1

尽管上面已经给出了很好的答案,但一个可能犯的小错误是创建一个没有任何主键的表。虽然看起来没有必要,但需要为每个表创建一个主键。否则上面的错误会被抛出。

于 2021-11-27T03:09:38.657 回答
0

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

于 2020-03-15T17:52:06.117 回答
0

在关系数据库表中,它必须需要候选键。你可以参考这篇文章https://en.wikipedia.org/wiki/Candidate_key

您只需要添加主键或复合主键。对于复合主键,您可以在 Flask APP 中使用以下行。无需导入任何东西。一切都将由 Flask 中的db变量处理。

在你的例子中,

db.PrimaryKeyConstraint(application_essay_id , application_essay_id )
于 2020-07-29T13:52:57.057 回答