web-dev-qa-db-fra.com

Comment simplifier les migrations dans Django 1.7?

Il y a déjà des questions similaires pour South, mais j'ai commencé mon projet avec Django 1.7 et je n'utilise pas South.

Au cours du développement, de nombreuses migrations ont été créées, mais le logiciel n’est pas encore fourni et il n’existe aucune base de données à migrer. Par conséquent, je souhaite réinitialiser les migrations comme si mon modèle actuel était celui d'origine et recréer toutes les bases de données.

Quelle est la façon recommandée de faire cela?

EDIT: À partir de Django 1.8, une nouvelle commande nommée migrations de squash permet de résoudre plus ou moins le problème décrit ici.

91
Kit Fisto

J'ai eu ça. Je viens de comprendre cela et c'est bon.

  • Tout d'abord, pour effacer le tableau des migrations:

    ./manage.py migrate --fake <app-name> zero
    
  • Supprimez le dossier ou le contenu app-name/migrations/.

  • Effectuer les migrations:

    ./manage.py makemigrations <app-name>
    
  • Enfin, nettoyez vos migrations sans apporter d’autres modifications à la base de données:

    ./manage.py migrate --fake <app-name>
    
137
kzorro

Dans la version Django 1.7 des migrations, la fonctionnalité de réinitialisation qui existait auparavant dans le sud a été abandonnée au profit d'une nouvelle fonctionnalité permettant de "réduire" vos migrations. Ceci est censé être un bon moyen de contrôler le nombre de migrations.

https://docs.djangoproject.com/en/dev/topics/migrations/#squashing-migrations

Si vous voulez toujours vraiment recommencer à zéro, je suppose que vous pourriez le faire en vidant la table des migrations et en supprimant les migrations, après quoi vous exécuteriez à nouveau makemigrations.

36
tijs

Je viens d'avoir le même problème. Voici ma solution de contournement.

#!/bin/sh
echo "Starting ..."

echo ">> Deleting old migrations"
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc"  -delete


# Optional
echo ">> Deleting database"
find . -name "db.sqlite3" -delete

echo ">> Running manage.py makemigrations"
python manage.py makemigrations

echo ">> Running manage.py migrate"
python manage.py migrate

echo ">> Done"

La commande find: http://unixhelp.ed.ac.uk/CGI/man-cgi?find

22
Abdelhamid Belarbi

En supposant que ceci soit la structure de votre projet,

project_root/
    app1/
        migrations/
    app2/
        migrations/
    ...
    manage.py
    remove_migrations.py

vous pouvez exécuter le script remove_migrations.py à partir de l'emplacement indiqué ci-dessus pour supprimer tous les fichiers de migration.

#remove_migrations.py
"""
Run this file from a Django =1.7 project root. 
Removes all migration files from all apps in a project.
""" 
from unipath import Path

this_file = Path(__file__).absolute()
current_dir = this_file.parent
dir_list = current_dir.listdir()

for paths in dir_list:
    migration_folder = paths.child('migrations')
    if migration_folder.exists():
        list_files = migration_folder.listdir()
        for files in list_files:
            split = files.components()
            if split[-1] != Path('__init__.py'):
                files.remove()

La suppression manuelle peut être fatigante si vous avez un projet complexe. Cela m'a fait gagner beaucoup de temps. La suppression des fichiers de migration est sécurisée. Je l'ai fait un énième nombre de fois sans rencontrer aucun problème ... pour le moment.

Cependant, lorsque j'ai supprimé le dossier de migration, makemigrations ou migrate ne m'a pas créé le dossier. Le script s'assure que le dossier de migration avec son __init__.py reste en place, ne supprimant que les fichiers de migration.

7
user4013889
  1. Supprimer des fichiers: delete_migrations.py (à la racine de prj):
import os

for root, dirs, files in os.walk(".", topdown=False):
  for name in files:
      if '/migrations' in root and name != '__init__.py':
          os.remove(os.path.join(root, name))
  1. DELETE FROM Django_migrations Where app in ('app1', 'app2');

  2. ./manage.py makemigrations

  3. ./manage.py migrer --fake

OU vous pouvez écrire la migration à partir de tout cela

6
Ibrohim Ermatov

J'essaie différentes commandes et certaines des réponses m'aident. Seule cette séquence dans mon cas a corrigé les dépendances brisées dans les migrations dans MYAPP et nettoyé toutes les migrations antérieures en partant de zéro.

Avant de le faire, assurez-vous que la base de données est déjà synchronisée (par exemple, n’ajoutez pas de nouveau champ Modèle ici ni ne modifiez les options Meta).

rm -Rf MYAPP/migrations/*
python manage.py makemigrations --empty MYAPP
python manage.py makemigrations
python manage.py migrate --fake MYAPP 0002

Où 0002 est le numéro de migration renvoyé par la dernière commande makemigrations.

Vous pouvez maintenant exécuter à nouveau makemigrations/migrate normalement car la migration 0002 est stockée mais pas reflétée dans la base de données déjà synchronisée.

4
chirale

Si vous ne vous souciez pas des migrations précédentes, pourquoi ne pas simplement supprimer toutes les migrations du répertoire migrations /? vous commencerez la séquence de migration à partir de zéro, en prenant votre modèle actuel comme référence, comme si vous aviez écrit le modèle entier maintenant.

Si vous ne me faites pas suffisamment confiance pour l'enlever, essayez plutôt de l'éloigner.

3
vokimon

Un moyen simple est

Accédez à chaque application et supprimez les fichiers de migration.

Ensuite, accédez à la table Django-migrtaions de la base de données et tronquez-la (supprimez toutes les entrées).

Après cela, vous pouvez créer à nouveau des migrations.

1
sprksh

Si vous êtes en mode de développement et que vous voulez simplement tout réinitialiser (base de données, migrations, etc.), j'utilise ce script basé sur la réponse de Abdelhamid Ba. Ceci effacera les tables de la base de données (Postgres), supprimera tous les fichiers de migration, relancera les migrations et chargera mes fixtures initiales:

#!/usr/bin/env bash
echo "This will wipe out the database, delete migration files, make and apply migrations and load the intial fixtures."

while true; do
    read -p "Do you wish to continue?" yn
    case $yn in
        [Yy]* ) make install; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done

echo ">> Deleting old migrations"
find ../../src -path "*/migrations/*.py" -not -name "__init__.py" -delete

# Optional
echo ">> Deleting database"
psql -U db_user -d db_name -a -f ./reset-db.sql

echo ">> Running manage.py makemigrations and migrate"
./migrations.sh

echo ">> Loading initial fixtures"
./load_initial_fixtures.sh

echo ">> Done"

fichier reset-db.sql:

DO $$ DECLARE
    r RECORD;
BEGIN
    -- if the schema you operate on is not "current", you will want to
    -- replace current_schema() in query with 'schematodeletetablesfrom'
    -- *and* update the generate 'DROP...' accordingly.
    FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
        EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
    END LOOP;
END $$;

fichier migration.sh:

#!/usr/bin/env bash
cd ../../src
./manage.py makemigrations
./manage.py migrate

fichier load_initial_fixtures.sh:

#!/usr/bin/env bash
cd ../../src
./manage.py loaddata ~/path-to-fixture/fixture.json

Veillez simplement à modifier les chemins correspondant à votre application. Personnellement, j'ai ces scripts dans un dossier appelé racine_projet/script/local, et les sources de Django sont dans racine_projet/src.

0
mrmuggles

Après avoir supprimé (manuellement) chaque dossier "migrations" de mon application, j'ai exécuté:

./manage.py dbshell
delete from Django_migrations;

Ensuite, j'ai pensé que je pouvais simplement faire ./manage.py makemigrations pour les régénérer tous. Cependant, aucun changement n'a été détecté. J'ai ensuite essayé de spécifier une application à la fois: ./manage.py makemigrations foo, ./manage.py makemigrations bar. Cependant, cela entraînait des dépendances circulaires qui ne pouvaient pas être résolues.

Enfin, j'ai exécuté une seule commande makemigrations qui spécifiait TOUTES mes applications (sans ordre particulier):

./manage.py makemigrations foo bar bike orange banana etc

Cette fois-ci, cela a fonctionné - les dépendances circulaires ont été automatiquement résolues (des fichiers de migration supplémentaires ont été créés si nécessaire).

Ensuite, j'ai pu exécuter ./manage.py migrate --fake et je suis rentré dans les affaires.

0
shacker

cd dans le répertoire src cd /path/to/src

supprimer les répertoires de migration rm -rf your_app/migrations/

notez que cela devrait être fait pour chaque application séparément

migrer python3.3 manage.py migrate

si vous souhaitez recommencer python3.3 manage.py makemigrations your_app

0
Rubber Duck