web-dev-qa-db-fra.com

django.db.utils.ProgrammingError: la relation existe déjà

J'essaie de configurer les tables pour un nouveau projet Django (autrement dit, les tables n'existent pas déjà dans la base de données); the Django version 1.7 et le back-end de la base est PostgreSQL. Le nom du projet est crud. Les résultats de la tentative de migration sont les suivants:

python manage.py makemigrations crud

Migrations for 'crud':
  0001_initial.py:
    - Create model AddressPoint
    - Create model CrudPermission
    - Create model CrudUser
    - Create model LDAPGroup
    - Create model LogEntry
    - Add field ldap_groups to cruduser
    - Alter unique_together for crudpermission (1 constraint(s))

python manage.py migrate crud

Operations to perform:
  Apply all migrations: crud
Running migrations:
  Applying crud.0001_initial...Traceback (most recent call last):
  File "manage.py", line 18, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python2.7/dist-packages/Django/core/management/__init__.py", line 385, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python2.7/dist-packages/Django/core/management/__init__.py", line 377, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python2.7/dist-packages/Django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/usr/local/lib/python2.7/dist-packages/Django/core/management/base.py", line 338, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python2.7/dist-packages/Django/core/management/commands/migrate.py", line 161, in handle
    executor.migrate(targets, plan, fake=options.get("fake", False))
  File "/usr/local/lib/python2.7/dist-packages/Django/db/migrations/executor.py", line 68, in migrate
    self.apply_migration(migration, fake=fake)
  File "/usr/local/lib/python2.7/dist-packages/Django/db/migrations/executor.py", line 102, in apply_migration
    migration.apply(project_state, schema_editor)
  File "/usr/local/lib/python2.7/dist-packages/Django/db/migrations/migration.py", line 108, in apply
    operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
  File "/usr/local/lib/python2.7/dist-packages/Django/db/migrations/operations/models.py", line 36, in database_forwards
    schema_editor.create_model(model)
  File "/usr/local/lib/python2.7/dist-packages/Django/db/backends/schema.py", line 262, in create_model
    self.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/Django/db/backends/schema.py", line 103, in execute
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/Django/db/backends/utils.py", line 82, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/Django/db/backends/utils.py", line 66, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/Django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/local/lib/python2.7/dist-packages/Django/db/backends/utils.py", line 66, in execute
    return self.cursor.execute(sql, params)
Django.db.utils.ProgrammingError: relation "crud_crudpermission" already exists

Quelques points forts du fichier de migration:

dependencies = [
    ('auth', '0001_initial'),
    ('contenttypes', '0001_initial'),
]
    migrations.CreateModel(
        name='CrudPermission',
        fields=[
            ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
            ('_created_by', models.CharField(default=b'', max_length=64, null=True, editable=False, blank=True)),
            ('_last_updated_by', models.CharField(default=b'', max_length=64, null=True, editable=False, blank=True)),
            ('_created', models.DateTimeField(null=True, editable=False, blank=True)),
            ('_last_updated', models.DateTimeField(null=True, editable=False, blank=True)),
            ('domain', models.CharField(max_length=32, choices=[(b'town', b'Town'), (b'boe', b'BOE'), (b'police', b'Police')])),
            ('ldap_group', models.CharField(max_length=128, verbose_name=b'LDAP group')),
            ('can_add', models.BooleanField(default=False, verbose_name=b'add')),
            ('can_change', models.BooleanField(default=False, verbose_name=b'change')),
            ('restrict_change_to_own', models.BooleanField(default=False)),
            ('can_delete', models.BooleanField(default=False, verbose_name=b'delete')),
            ('restrict_delete_to_own', models.BooleanField(default=False)),
            ('models', models.ManyToManyField(to='contenttypes.ContentType', null=True, blank=True)),
        ],
        options={
            'verbose_name': 'CRUD permission',
        },
        bases=(models.Model,),
    ),
    migrations.AlterUniqueTogether(
        name='crudpermission',
        unique_together=set([('ldap_group', 'can_add', 'can_change', 'can_delete', 'domain')]),
    )

,

L'application crud n'a pas pour vocation de faire quoi que ce soit, mais je l'utilise avec une autre application. Par conséquent, lorsque j'essaie de migrer depuis cette application, je déclenche le problème ci-dessus.

J'ai trouvé d'autres exemples sur le Web de personnes ayant des problèmes similaires, mais aucune de leurs affaires ne semble s'appliquer, car

  1. Le problème concerne toute une relation, pas seulement une colonne
  2. Je n'utilise pas l'héritage multiple.

Où devrais-je chercher ensuite le problème sous-jacent?

59
quindraco

Cela fonctionne très bien

./manage.py migrate --fake default

Source: - https://github.com/nijel/weblate/issues/587

61
trex

Faire python manage.py migrate --fake initialement.

Lire https://docs.djangoproject.com/fr/1.9/ref/Django-admin/#Django-admin-migrate

30
Mudassar Hashmi

Ayant été confronté à un problème similaire, a finalement supprimé tous les fichiers .py du dossier de migration (Django 1.7 en crée automatiquement un), a parfaitement fonctionné par la suite.

6
Rickka

J'ai rencontré un problème similaire lorsque j'ai ajouté quelques nouveaux champs au modèle existant. J'utilise Django 1.9, qui introduit--run-syncdb option. Fonctionnement manage.py migrate --run-syncdb corrigé mes tables.

5
roboslone

Je faisais face à des problèmes similaires, où j'avais changé le nom de la colonne. J'obtenais la même erreur que celle mentionnée dans la pile-trace fournie avec la question.

Voici ce que j'ai fait.

J'ai d'abord fait de fausses migrations. Ensuite, j'ai supprimé son entrée (migrations que je voulais exécuter) de la table Django_migrations et j'ai de nouveau exécuté les migrations (pas de faux cette fois).

Les changements sont apparus comme prévu pour moi.

j'espère que c'est utile.

4
Vishal Mopari

Django fournit un --fake-initial option que j’ai trouvée efficace pour mon utilisation. Depuis le Django Migration Documentation :

--fake-initial

Permet à Django) d'ignorer la migration initiale d'une application si toutes les tables de base de données portant les noms de tous les modèles créés par toutes les opérations CreateModel dans cette migration existent déjà. Cette option est destinée à être utilisée lors de la première migration base de données qui préexistait à l’utilisation des migrations. Cette option ne vérifie toutefois pas la correspondance du schéma de base de données au-delà des noms de table correspondants et ne peut donc être utilisée en toute sécurité que si vous êtes sûr que votre schéma existant correspond à ce qui a été enregistré dans votre migration initiale.

Pour mon usage, je venais de tirer un projet du contrôle de version et me préparais à ajouter de nouveaux champs de modèle. J'ai ajouté les champs, a couru ./manage.py makemigrations puis a tenté de lancer ./manage.py migrate qui a jeté l'erreur puisque, comme on pouvait s'y attendre, de nombreux champs existaient déjà dans la base de données existante.

Ce que j'aurais dû faire était d'exécuter makemigrations immédiatement après l'extraction du projet du contrôle de versions pour créer un instantané de l'état des modèles existants. Ensuite, lancez le ./manage.py migrate --fake-initial serait la prochaine étape.

Après cela, vous pouvez ajouter et makemigrations> migrate comme d'habitude.

NOTE: Je ne sais pas si un --fake-initial _ ignorerait les champs existants et en ajouterait de nouveaux. J'ai choisi de commenter les nouveaux champs que j'avais créés jusque-là, lancez le --fake-initial _ comme si c’était la première chose que j’ai faite après avoir extrait le contrôle de version, alors ajouté dans des champs mis à jour lors de la prochaine migration.

Autre documentation connexe: https://docs.djangoproject.com/en/dev/topics/migrations/#initial-migrations

3
theeastcoastwest

Maintenant (j'utilise Django 1.9) vous pouvez créer:

./ manage.py [--database DATABASE] --fake [app_label] [nom_migration]

De cette façon, vous ciblez le problème avec plus de précision et vous ne pouvez simuler que la migration problématique sur la base de données spécifique.

Donc, en regardant la question, vous pourriez:

./ manage.py --database default --fake crud crud.0001_initial

3
Raydel Miranda

J'ai trouvé ce problème dans web2pyframework dans models/config.py.

Changement

settings.base.migrate = True

sur le fichier de configuration à

settings.base.migrate = False

Problème résolu.

1
R.kiani

J'ai trouvé et résolu un exemple particulier de cette erreur dans un projet Django 1.10) alors que je changeais un champ de clé étrangère nommé member pour qu'il pointe vers une autre table. Dans ma première tentative, j’ai renommé member en member_user et essayé de créer un nouveau champ member sous la forme d’une clé étrangère. montrant la nouvelle table, mais cela n'a pas fonctionné.

Ce que j’ai trouvé, c’est que lorsque je renommais la colonne member, il ne modifiait pas le nom de l’index sous la forme <app>_<model>_<hash> Et lorsque j’essayais de créer une nouvelle colonne member, il essayait de créez le même nom d'index car la partie de hachage du nom était la même.

J'ai résolu le problème en créant une nouvelle relation member_user Temporairement et en copiant les données. Cela a créé un nouvel index avec un hachage différent. J'ai ensuite supprimé member et l'ai recréé en pointant vers la nouvelle table et avec elle le nom d'index potentiellement conflictuel. Une fois cela fait, j’ai exécuté l’étape RunPython pour renseigner la nouvelle colonne member avec des références à la table applicable. J'ai fini par ajouter RemoveField migrations pour nettoyer les colonnes temporaires member_user.

J'ai dû diviser mes migrations en deux fichiers car j'ai reçu cette erreur:

psycopg2.OperationalError: impossible d'ALTER TABLE "<nom_table>" car des événements de déclencheur sont en attente

Après la création et la copie des données dans member_user, Je n'ai pas pu supprimer member dans la même transaction de migration. Cela peut être une limitation spécifique à Postgres, mais cela a été facilement résolu en créant une autre transaction et en déplaçant tout après la création et la copie de member_user Dans la deuxième migration.

1
Shaun Kruger