web-dev-qa-db-ja.com

マップされたテーブルの主キー列を組み立てることができませんでした

データベーススキーマの移行を作成しようとすると、この奇妙なエラーが発生します。何が悪いのかを理解するのを手伝ってくれませんか?

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

テーブルに2つの主キーを含めることはできません。代わりに、複合主キーを使用する必要があります。これは、以下のようにモデルに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")
32
Minh Pham

このエラーが発生するのは、Column()定義の後にコンマがあり、_application_essay_id_および_theme_essay_id_が、Columnだけではなく、Columnを含む1要素のタプルとして解析されるためです。 。これにより、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のコンマ区切りのシーケンスを引数として渡すことを含むモデル/テーブルを宣言するための構文が含まれているため(たとえば、op.create_table()またはTable()コンストラクターに) )およびクラスのプロパティとしてColumnsを使用してクラスを宣言することを含むその他の場合、最初の構文から2番目の構文にColumn宣言をカットアンドペーストし、コンマの一部を削除するのを忘れることで、このエラーが発生しますreally easy 。この簡単な間違いが、この質問が非常に多くのビューを持っている理由だと思います。この回答を投稿した時点では、16000を超えています。

39
Mark Amery