J'ai démarré un projet Django 1.8, qui utilise le système de migration.
En quelque sorte, au fil du temps, les choses ont mal tourné. J'ai donc effacé les dossiers et la table des migrations de la base de données et j'essaie maintenant de les reconstruire, sans succès.
J'ai trois applications (3 fichiers models.py
), Et les modèles reflètent EXACTEMENT les tables!
La meilleure approche que j'ai trouvée jusqu'à présent était:
migrations
. Terminé!Django_migrations
. Terminé!python manage.py makemigrations --empty <app>
Pour chaque application. Terminé!python manage.py migrate --fake
. Terminé! (Bien que cela ne fonctionne que si je le lance après chaque commande makemigrations
.Maintenant, j'ajoute un nouveau champ, lance la commande makemigrations
et le message d'erreur suivant s'affiche:Django.db.utils.OperationalError: (1054, "Unknown column 'accounts_plan.max_item_size' in 'field list'")
J'ai brûlé des heures sur cette chose. Comment puis-je initialiser les migrations pour pouvoir continuer à travailler sans interruption de migration à chaque fois?
Pourquoi est-ce si compliqué? Pourquoi n’existe-t-il pas une seule ligne: initiate_migrations_from_schema
?
MODIFIER:
Maintenant, les choses deviennent encore plus mauvaises. J'ai tronqué la table Django_migrations
Et supprimé tout le dossier migrations
.
Maintenant, j'essaie d'exécuter python manage.py migrate --fake-initial
(Quelque chose que j'ai trouvé dans la documentation DEV), juste pour qu'il configure toutes les applications 'internes' de Django (auth, session, etc.) et j'obtiens :(1054, "Unknown column 'name' in 'Django_content_type'")
.
Maintenant, cette "colonne" n'est pas une vraie colonne. C'est un @property
Défini dans l'application contenttypes
de Django. WHAT IS EN COURS ICI? Pourquoi identifie-t-il la propriété name
en tant que colonne réelle?
Je l'ai enfin fait fonctionner, bien que je ne sache pas pourquoi et j'espère que cela fonctionnera à l'avenir.
Après avoir effectué de nombreux essais et avoir consulté le site de développement de Django ( lien ).
Voici les étapes (pour quiconque se heurte à ce problème):
Django_migrations
table: delete from Django_migrations;
migrations
: rm -rf <app>/migrations/
python manage.py migrate --fake
python manage.py makemigrations <app>
. Occupez-vous des dépendances (les modèles avec ForeignKey doivent fonctionner après leur modèle parent).python manage.py migrate --fake-initial
Après cela, j'ai exécuté la dernière commande sans le --fake-initial
drapeau, juste pour être sûr.
Maintenant tout fonctionne et je peux utiliser le système de migration normalement.
Je suis sûr que je ne suis pas le seul à rencontrer ce problème. Il doit être mieux documenté et même simplifié.
Mise à jour pour Django 1.9 utilisateurs:
J'ai eu ce scénario à nouveau avec un Django 1.9.4, et l'étape 5 a échoué.
Il me suffisait de remplacer --fake-initial
avec --fake
pour le faire fonctionner.
J'ai rencontré ce scénario mais je n'ai jamais eu à abandonner la base de données pour le résoudre. Généralement, je supprime le dossier de migration de l'application et supprime les entrées de migration de la base de données.
J'essayais de faire des migrations une application à la fois. Si l'une des applications s'appuie sur d'autres tables, ajoutez-les évidemment en dernier.
De plus, je viens généralement de lancer python manage.py makemigrations puis juste python manage.py migrate Même avec la migration initiale, tout devrait bien fonctionner avec Django 1.7 et 1.8.
Django ..., 1.8, 1.9, ...
Ce que vous voulez réaliser, c'est écraser les migrations existantes et utiliser leur remplacement.
Comment le faire correctement sans utiliser de commande lors de la libération (un cas sans impact sur la base de données et les collègues).
Pour chaque application, supprimez son dossier de migration: mv <app>/migrations/ <app>/migrationsOLD/
Pour chaque exécution de cette application: python manage.py makemigrations <app>
.
Personnalisez chaque nouvelle migration:
si vous avez un application complexe, ou plusieurs applications et modèles associés entre eux, afin d'éviter CircularDependencyError
ou ValueError: Unhandled pending operations for models
:
prépare la deuxième migration vide dans <app>
0002_initial2.py
_ (mettez sa dépendance à app_other::0001_initial.py
et <app>
:: 0001_initial.py
_ ainsi - tous les modèles ForeignKey, M2M liés aux modèles créés lors de l'étape de migration 0001 dans d'autres applications)
Tout doit être en ordre - parfois, il faudra plus de migrations pour se préparer. Prenez soin de l'attribut dependencies
ici dans chaque migration.
s'occuper des valeurs initiales - vérifiez vous-même toutes les RunPython
actions de migrationsOLD
et copiez le code dans la nouvelle migration initiale si nécessaire.
(optionnel pour --fake-initial
) Ajouter initial=True
à toutes les nouvelles classes de migration (0002 aussi si a été ajouté).
replaces
dans la nouvelle classe de migration. (comme propre custom a squashmigrations
). Mettez là toutes les anciennes migrations de <app>
Tout vérifier avec makemigrations
.
affirmer "Aucun changement détecté"
Vérifier si migrate -l
montrer [x] partout
affirmer similaire:
[X] 0001_initial
[X] 0002_initial2 (102 migrations écrasées)
Exemple:
Pour vieux:
0001_initial.py
0002_auto.py
...
0103_auto.py
préparer:
0001_initial.py
0002_initial2.py (optional but sometimes required to satisfy dependency)
et ajoutez à replaces
à la dernière (0002 ici, peut être 0001):
replaces = [(b'<app>', '0002_auto.py'), ..., (b'<app>', '0103_auto.py')]
0001_initial.py doit être nommé de la même manière que l'ancien.
0002_initial2.py est nouveau, mais il remplace les anciennes migrations donc Django le traitera comme chargé.
Si vous utilisez des routeurs, cela pourrait poser un problème. Méthode de vérification allow_migrate
s'il est exécuté correctement dans routers.py
. Essayez de définir toujours la valeur de retour sur True
et vérifiez si le problème est résolu.
def allow_migrate(self, db, app_label, model_name=None, **hints):
return True