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

Python 无法为映射表组装任何主键列,python,sqlalchemy,flask-sqlalchemy,flask-migrate,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' 我的型

当我尝试创建数据库模式迁移时,我遇到了一个奇怪的错误。你能帮我弄清楚出了什么问题吗

$ 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")

表中不能有两个主键。相反,必须使用复合主键。 这可以通过如下方式在模型中添加一个
PrimaryKeyConstraint
来实现(记住在
\u table\u args\u\u关闭括号之前添加一个逗号):

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")

出现此错误是因为在
Column()
定义后有尾随逗号,这会导致
application\u-assessment\u-id
theme\u-assessment\u-id
被解析为一个包含
列而非
列的单元素元组。这会阻止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),

然后您的错误将被修复


旁白:由于SQLAlchemy(以及Alembic和Flask SQLAlchemy)包含一些用于声明模型/表的语法,这些模型/表涉及将以逗号分隔的
s序列作为参数传递(例如to
op.create_table()
table()
构造函数)还有一些涉及将
声明为类属性的类,通过将
声明从第一个语法剪切和粘贴到第二个语法,并忘记删除一些逗号,很容易出现这种错误。我怀疑这一容易犯的错误是这个问题有如此大的错误的原因ge视图数-在我发布此答案时超过16000个。

我之所以出现此错误是因为语法错误。I.v在我的声明中拼错了“primary_key”

在关系数据库表中,它必须需要候选键。您可以参考本文

您只需添加主键或复合主键。对于复合主键,您可以在Flask应用程序中使用下一行。无需导入任何内容。所有内容都将由Flask中的db变量进行处理

以你为例,

db.PrimaryKeyConstraint(application_essay_id , application_essay_id )

一个表中可以有两个主键!ref:@karantan,不,一个表中不能有两个主键——从定义上来说,这是不可能的。doco页面显示的是,一个主键中可以有多个列。在某些DBMS中,您还可以声明附加的
唯一键
约束,这些约束具有prima的许多属性ry键,但根据定义,不是“主键”。-1这是胡说八道。在SQLAlchemy模型中,两列的
primary\u key=True
是完全合法的(尽管@ChrisJohnson指出,这会创建一个复合主键,而不是“两个主键”)这并不是这里错误的原因。唉,如果我这样做,我没有得到正确的设置,相反,我得到了所需的两列组合唯一索引,但每列上也有单独的唯一约束,这会破坏一切。还不清楚为什么。你可以将多列声明为主键,sqlalchemy会将其转换为compound keydevelopers\u抓住了\u this+=1谢谢你的回答-这不仅是正确的,一年后我也遇到了同样的问题:)我忘记添加属性名-(应用程序\u文章id=
部分)由于复制粘贴
主键=False
vs True…:/这些小事情会让你花很多时间去发现…:如果其他人犯了我犯过的同样令人愤怒的错误,那么如果在创建
列时使用
而不是
=
(就像在pydantic模型中一样),也会出现此错误。
db.PrimaryKeyConstraint(application_essay_id , application_essay_id )