web-dev-qa-db-fra.com

Erreur de migration Django: la colonne n'existe pas

Python 3, Django 1.8.5, Postgres

J'ai un modèle Sites qui a bien fonctionné. J'ai récemment essayé d'ajouter un champ, airport_code et de migrer les données.

class Site(BaseModel):

  objects = SiteManager()

  name = models.CharField(max_length=200, unique=True)
  domain = models.CharField(max_length=200, unique=True)
  weather = models.CharField(max_length=10)
  nearby_sites = models.ManyToManyField('self', symmetrical=False, blank=True)
  users = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)
  facebook = models.URLField(max_length=200)
  Twitter = models.URLField(max_length=200)
  header_override = models.TextField(blank=True)
  email_header_override = models.TextField(blank=True)
  timely_site_tag_id = models.IntegerField()
  timely_featured_tag_id = models.IntegerField()
  timely_domain = models.CharField(max_length=255)
  sitemap_public_id = models.CharField(max_length=255)
  state = models.CharField(max_length=24)
  airport_code = JSONField()

Cependant, quand j'ai lancé makemigrations j'ai eu une erreur:

Django.db.utils.ProgrammingError: column sites_site.airport_code does not exist LINE 1: ..._site"."sitemap_public_id", "sites_site"."state", "sites_sit...

Bien sûr, cela n’a aucun sens, car la colonne n’existe évidemment pas lorsque je tente de la créer dans la migration.

J'ai rencontré de nombreuses questions sur ce bogue sur Stack Overflow qui n'ont pas encore été résolues ou qui proposent une solution permettant de créer manuellement le fichier de migration ou de détruire et de reconstruire la base de données. Ce n'est pas une solution acceptable.

18
Alex

Ce bogue a été résolu pour moi en commentant la barre d’outils de débogage de Django dans INSTALLED_APPS dans settings.py. Je ne suis pas sûr de savoir pourquoi la barre d’outils de débogage est le coupable, mais après l’avoir commentée, j’ai pu exécuter makemigrations et migrate sans problème.

En espérant que cela aide quelqu'un, j'ai passé douze heures à essayer de le comprendre.

7
Alex

Après avoir exécuté makemigrations, veillez à parcourir pas à pas la trace de la pile. 

Dans mon cas, j’ai remarqué que cela avait été tracé grâce à un appel à un formulaire contenu dans un formulaire.py dans une application complètement différente, ce qui entraînait un appel au modèle pour lequel je tentais de créer une nouvelle migration.

Déplacer la classe Form de forms.py vers le fichier views.py a résolu le problème.

9
Nexus

Dans mon cas, c'était parce que j'avais une contrainte unique_together qui avait été définie.

Lorsque je voulais supprimer un champ, la migration générée automatiquement tentait de supprimer le champ avant de supprimer la contrainte unique_together.

Ce que je devais faire était déplacer manuellement la contrainte migrations.AlterUniqueTogether dans le fichier de migration, afin que Django supprime d'abord la contrainte avant d'essayer de supprimer le champ.

J'espère que cela peut aider quelqu'un.

3
darksider

J'ai aussi rencontré ce problème et la réponse de @Nexus a aidé. Je pensais donner des détails sur mon cas particulier ici pour mieux illustrer la cause du problème. Cela semble être un bug potentiel pour moi.

J'ai un modèle Brand comme suit:

class Brand(BaseModelClass):
    name = CharField(max_length=256, unique=True)
    website = ForeignKey(URL, on_delete=CASCADE, null=True, blank=True)

J'exécutais un python manage.py makemigrations après avoir ajouté un champ Boolean comme suit:

class Brand(BaseModelClass):
    name = CharField(max_length=256, unique=True)
    website = ForeignKey(URL, on_delete=CASCADE, null=True, blank=True)
    trusted = Boolean(default=True)

Lors de l'exécution de la commande makemigrations, j'ai reçu une erreur similaire à celle de l'OP:

Django.db.utils.ProgrammingError: column appname_brand.trusted does not exist

Selon la suggestion de @Nexus, j'ai parcouru la pile, ligne par ligne, en supposant qu'il ne s'agissait pas d'un problème fondamental avec Django. Il se trouve que, dans l’un des fichiers apps forms.py, j’avais les caractéristiques suivantes:

choices={(str(brand.id), brand.name) for brand in Brand.objects.all()}

La solution consistait simplement à commenter cette ligne, à exécuter manage.py makemigrations, puis à exécuter manage.py migrate. Ensuite, j'ai annulé la ligne et tout, et la fonctionnalité de mes formulaires fonctionnait comme avant.

2
theeastcoastwest

Coincé dans cette question récemment.

Dans mon cas, j'ai ajouté une référence à un champ non existant dans le code, puis je suis arrivé dans le fichier de modèle et ajouté le nouveau champ, puis j'ai essayé d'exécuter la commande makemigrations qui a renvoyé l'erreur ci-dessus. 

Je suis donc allé à la trace de la pile tout en haut et j'ai trouvé que le problème venait de la nouvelle référence ajoutée. a commenté cela, a couru makemigrations et le tour est joué.

0
Shobi

J'ai le même problème (la colonne n'existe pas) mais lorsque j'essaie d'exécuter migrate pas avec makemigrations

  • Cause: j'ai supprimé les fichiers de migration et les ai remplacés par le fichier de migration initiale simulant unique 0001 avant d'exécuter la migration pour la dernière modification.

  • Solution: 

    1. Supprimez les tables impliquées dans la migration de cette application (envisagez une solution de contournement pour la sauvegarde, le cas échéant)
    2. Supprimez les lignes responsables de la migration de cette application de la table Django_migrations dans laquelle les migrations sont enregistrées. Voici comment Django sait quelles migrations ont été appliquées et lesquelles doivent encore être appliquées.

Et voici comment résoudre ce problème:

  • connectez-vous en tant qu'utilisateur postgres (mon utilisateur s'appelle posgres):

    Sudo -i -u postgres

  • Ouvrez un terminal SQL et connectez-vous à votre base de données:

    psql -d database_name

  • Listez votre table et repérez les tables liées à cette application:

    \dt

  • Supprimez-les (considérez l'ordre de suppression avec les relations):

    DROP TABLE tablename ;

  • Listez l'enregistrement de migration, vous verrez les migrations appliquées classées comme suit:

id | app | nom | appliqué
- + ------ + -------- + --------- +

SELECT * FROM Django_migrations;
  • Supprimez les lignes des migrations de cette application (vous pouvez supprimer par identifiant ou par application, avec application, n'oubliez pas les «guillemets»):

    DELETE FROM Django_migrations WHERE app='your_app';

  • déconnectez-vous et lancez simplement vos migrations (peut-être lancer makemigrations dans votre cas):

    python manage.py migrate --settings=your.settings.module_if_any

Remarque: il est possible que, dans votre cas, vous n'ayez pas à supprimer toutes les tables de cette application et non toutes les migrations, mais uniquement celles des modèles à l'origine du problème.

Je souhaite que cela peut aider.

0
Yahya Yahyaoui

J'ai rencontré ce problème récemment après la mise à niveau vers Django 1.11. Je voulais régler le problème de façon permanente afin de ne pas avoir à commenter/décoder le code à chaque fois que j'effectuais une migration sur la table. Mon approche est la suivante:

from Django.db.utils import ProgrammingError as AvoidDataMigrationError

try:
    ... do stuff that breaks migrations
except AvoidDataMigrationError:
    pass

Je renomme l'exception lors de l'importation en AvoidDataMigrationError, il est donc clair pourquoi elle est présente.

0
Jeff Bauer