Lorsque j'essaie de créer une migration de schéma de base de données, j'obtiens cette erreur étrange. Pouvez-vous m'aider à comprendre ce qui ne va pas?
$ 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'
Mon modèle:
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")
Vous ne pouvez pas avoir deux clés primaires dans une table. Au lieu de cela, vous devez utiliser une clé primaire composée. Cela peut être fait en ajoutant un PrimaryKeyConstraint
dans votre modèle comme ci-dessous (n'oubliez pas d'ajouter une virgule avant de fermer le support dans __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")
Vous obtenez cette erreur car vous avez des virgules après vos définitions de Column()
, ce qui fait que application_essay_id
Et theme_essay_id
Sont chacun analysés comme un tuple à un élément contenant un Column
au lieu d'un Column
. Cela empêche SQLAlchemy de "voir" que les colonnes sont présentes et, par conséquent, votre modèle ne contient aucune colonne de clé primaire.
Si vous remplacez simplement
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),
avec
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)
alors votre erreur sera corrigée.
En plus: puisque SQLAlchemy (et Alembic et Flask-SQLAlchemy) contiennent des syntaxes pour déclarer des modèles/tables qui impliquent de passer une séquence séparée par des virgules de Column
s comme arguments (par exemple à op.create_table()
ou Table()
constructor) et d'autres qui impliquent de déclarer une classe avec Column
s comme propriétés de classe, c'est vraiment facile de rencontrer cette erreur en coupant et collant Column
déclarations de la première syntaxe à la seconde et oubliant de supprimer certaines virgules. Je soupçonne que cette erreur facile à faire est la raison pour laquelle cette question a un si grand nombre de vues - plus de 16 000 au moment où je poste cette réponse.