¿Cómo simplificar las migraciones en Django 1.7?

92

Ya hay preguntas similares para South, pero comencé mi proyecto con Django 1.7 y no estoy usando South.

Durante el desarrollo se han creado muchas migraciones, sin embargo, el software aún no se ha entregado y no existe ninguna base de datos que deba migrar. Por lo tanto, me gustaría restablecer las migraciones como si mi modelo actual fuera el original y volver a crear todas las bases de datos.

¿Cuál es la forma recomendada de hacerlo?

EDITAR: A partir de Django 1.8 hay un nuevo comando llamado squashmigrations que resuelve más o menos el problema descrito aquí.

Kit Fisto
fuente
¿Qué significa restablecer una migración? ¿Deshacerlo?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

137

Tengo esto. Me acabo de dar cuenta de esto y es bueno.

  • Primero, para borrar la tabla de migraciones:

    ./manage.py migrate --fake <app-name> zero
  • Eliminar app-name/migrations/carpeta o contenido.

  • Realiza las migraciones:

    ./manage.py makemigrations <app-name>
  • Finalmente, arregle sus migraciones sin hacer otros cambios en la base de datos:

    ./manage.py migrate --fake <app-name>
kzorro
fuente
5
Esta es una buena respuesta. El simple hecho de eliminar las migraciones no deshace el daño que causaron las migraciones defectuosas. De hecho, esto limpia la pizarra y le permite empezar de nuevo.
Rogueleaderr
15
Si elabora un poco, esta debería ser la respuesta aceptada.
tani-rokk
8
Excelente respuesta de una línea hermano, no tengo idea de lo que hace esto
bischoffingston
13
Esta línea simplemente invierte las migraciones una por una, hasta que zero. Para el sistema de migraciones Django, <app-name> ahora es una nueva aplicación y makemigrations <app-name>comenzará desde 0001. --fakeevita que las tablas se modifiquen realmente, que las migraciones solo se deben marcar como invertidas y no se deben aplicar al esquema. (Añadiendo pequeñas explicaciones en aras de la integridad, @ tani-rokk, @Fabrizio)
Mir Nazim
17
manage.py migrate --fake <app-name> zeropara borrar la tabla de migraciones, luego elimine la carpeta <app-name> / migrations / o su contenido. Entonces manage.py makemigrations <app-name>y finalmente hazlo manage.py migrate --fake <app-name>. Esto pondrá en orden sus migraciones sin realizar otros cambios en la base de datos.
doeke
36

En la versión de migraciones de Django 1.7, la funcionalidad de restablecimiento que solía estar en el sur se ha eliminado a favor de una nueva funcionalidad para "aplastar" sus migraciones. Se supone que esta es una buena manera de mantener bajo control el número de migraciones.

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

Si aún desea comenzar desde cero, supongo que aún podría vaciar la tabla de migraciones y eliminar las migraciones, después de lo cual volvería a ejecutar makemigrations.

tijs
fuente
2
¿Cómo "eliminaría las migraciones" además de vaciar la tabla de migraciones? ¿Eliminaría toda la carpeta o solo los archivos 00X _ *. Py?
Kit Fisto
con South puede eliminar la carpeta de migraciones que se volverá a crear cuando ejecute makemigrations nuevamente. Supongo que esto funciona igual para Django 1.7
tijs
4
Solo una nota. en Django 1.7, si usted, sin cuidado, elimina la carpeta de migración, puede generar una excepción si su modelo es hijo de otroraise KeyError("Migration %s dependencies reference nonexistent parent node %r" % (migration, parent))
Algoritmático
Específicamente ./manage.py squashmigrations myapp 0004, aplastará todas las migraciones antes de la migración 0004en su aplicación myapp. Esto creará una única migración aplastada.
Bryce Guinta
22

Acabo de tener el mismo problema. Aquí está mi solución.

#!/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"

El findcomando: http://unixhelp.ed.ac.uk/CGI/man-cgi?find

Abdelhamid Belarbi
fuente
13
esto elimina los datos, no solo las migraciones
hobs
2
también debería eliminar los archivos
.pyc
7

Suponiendo que esta es la estructura de su proyecto,

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

puede ejecutar el script remove_migrations.py desde el lugar indicado arriba para borrar todos los archivos de migraciones.

#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()

Eliminar manualmente puede ser agotador si tiene un proyecto elaborado. Esto me ahorró mucho tiempo. Eliminar archivos de migración es seguro. He hecho esto una enésima cantidad de veces sin enfrentar ningún problema ... todavía.

Sin embargo, cuando eliminé la carpeta de migraciones, makemigrationso migrateno la volví a crear. El script se asegura de que la carpeta de migración con su __init__.pyubicación permanezca, solo borrando los archivos de migración.


fuente
simplemente puede eliminar las carpetas de migraciones y volver a crearlas con un init .py vacío (por ejemplo touch migrations/__init__.py)
hobs
6
  1. Eliminar archivos: delete_migrations.py (en la raíz 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 migrate --fake

O, puede escribir la migración de todos estos

Ibrohim Ermatov
fuente
Tuve que especificar los nombres de las aplicaciones para ./manage.py makemigrationsque funcionaran, así:./manage.py makemigrations orders alerts
Salami
4

Intento diferentes comandos y algunas de las respuestas me ayudan. Solo esta secuencia en mi caso solucionó ambas dependencias rotas en las migraciones en MYAPP y limpió todas las migraciones pasadas comenzando desde cero.

Antes de hacer esto, asegúrese de que la base de datos ya esté sincronizada (por ejemplo, no agregue un nuevo campo Modelo aquí o cambie las opciones de Meta).

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

Donde 0002 es el número de migración devuelto por el último comando makemigrations.

Ahora puede ejecutar makemigrations / migrate de nuevo normalmente porque la migración 0002 se almacena pero no se refleja en la base de datos ya sincronizada.

chirale
fuente
De todas las soluciones mencionadas anteriormente, solo esto funcionó para mí sin un problema técnico y sin eliminar la base de datos.
Vivek Jha
3

Si no le importan las migraciones anteriores, ¿qué tal simplemente eliminar todas las migraciones en el directorio migrations /? Comenzará la secuencia de migración desde cero, tomando su modelo actual como referencia como si hubiera escrito el modelo completo ahora.

Si no confías en mí para eliminarlos, intenta hacerlo en su lugar.

vokimon
fuente
¿Cuál es la importancia de mantener antiguas migraciones? Mis preguntas llegan al suelo cuando uno intenta actualizar de django 1.6 a 1.8.
Jay Modi
Las migraciones son simplemente un registro de los cambios que ha realizado en la base de datos. He seguido el consejo de vokiman más de una vez cuando mi cadena de migración deja de funcionar.
Adam Starrh
1

Una forma sencilla es

Vaya a todas las aplicaciones y elimine los archivos de migración.

Luego vaya a la tabla django-migrtaions en la base de datos y trunque (elimine todas las entradas).

Después de eso, puede crear migraciones una vez más.

Sprksh
fuente
1
mientras elimina los archivos de migración, asegúrese de no eliminar los archivos de inicio .
sprksh
Esto realmente me ayudó. He eliminado todas las migraciones, dejó caer las tablas de mi base de datos SQLite, pero aún era incapaz de makemigrations ... Sin embargo, una vez que restauró la _init_ archivos .py (DOH) pude makemigrations de nuevo y de crucero. @sprksh = ¡Salvavidas!
twknab
0

cd al directorio src cd /path/to/src

eliminar directorios de migración rm -rf your_app/migrations/

tenga en cuenta que esto debe hacerse para cada aplicación por separado

emigrar python3.3 manage.py migrate

si quieres empezar de nuevo python3.3 manage.py makemigrations your_app

Pato de goma
fuente
0

Si está en modo de desarrollo y solo desea restablecer todo (base de datos, migraciones, etc.), uso este script basado en la respuesta de Abdelhamid Ba. Esto borrará las tablas de la base de datos (Postgres), eliminará todos los archivos de migración, volverá a ejecutar las migraciones y cargará mis accesorios iniciales:

#!/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"

Archivo 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 $$;

archivo migration.sh:

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

archivo load_initial_fixtures.sh:

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

Solo asegúrese de cambiar las rutas para que correspondan a su aplicación. Yo personalmente tengo estos scripts en una carpeta llamada project_root / script / local, y las fuentes de django están en project_root / src.

mrmuggles
fuente
0

Después de eliminar cada carpeta de "migraciones" en mi aplicación (manualmente), ejecuté:

./manage.py dbshell
delete from django_migrations;

Entonces pensé que podía hacer ./manage.py makemigrationspara regenerarlos a todos. Sin embargo, no se detectaron cambios. Luego intenté especificar una aplicación a la vez: ./manage.py makemigrations foo, ./manage.py makemigrations bar. Sin embargo, esto dio lugar a dependencias circulares que no se pudieron resolver.

Finalmente, ejecuté un solo comando makemigrations que especificaba TODAS mis aplicaciones (sin ningún orden en particular):

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

Esta vez, funcionó: las dependencias circulares se resolvieron automáticamente (creó archivos de migraciones adicionales cuando fue necesario).

Luego pude correr ./manage.py migrate --fakey volví al negocio.

coctelera
fuente