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
Où devrais-je chercher ensuite le problème sous-jacent?
Cela fonctionne très bien
./manage.py migrate --fake default
Faire python manage.py migrate --fake
initialement.
Lire https://docs.djangoproject.com/fr/1.9/ref/Django-admin/#Django-admin-migrate
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.
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.
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.
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
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
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.
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.