¿Cómo revertir la última migración?

6 minutos de lectura

Avatar de usuario de Ronen Ness
Ronen Ness

Realicé una migración que agregó una nueva tabla y quiero revertirla y eliminar la migración, sin crear una nueva migración.

¿Cómo lo hago? ¿Hay un comando para revertir la última migración y luego simplemente puedo eliminar el archivo de migración?

Avatar de usuario de Alasdair
Alasdair

Puedes volver por migrando a la migración anterior.

Por ejemplo, si sus dos últimas migraciones son:

  • 0010_previous_migration
  • 0011_migration_to_revert

Entonces harías:

./manage.py migrate my_app 0010_previous_migration 

En realidad, no necesita usar el nombre de migración completo, el número es suficiente, es decir

./manage.py migrate my_app 0010 

A continuación, puede eliminar la migración 0011_migration_to_revert.

Si está utilizando Django 1.8+, puede mostrar los nombres de todas las migraciones con

./manage.py showmigrations my_app

Para revertir todas las migraciones de una aplicación, puede ejecutar:

./manage.py migrate my_app zero

  • He visto muchas respuestas en SO a este problema que son antiguas y simplemente ya no funcionan. +1 porque esto funciona con Django 1.8.

    – Alan SE

    7 de marzo de 2016 a las 14:11

  • ¿Normalmente los usuarios también quieren eliminar el archivo de migración? A menudo me encuentro haciendo una migración, luego la reconsidero y la vuelvo a crear antes de enviar algo limpio, por lo que generalmente necesito recordar ‘rm path/to/0011_migration_to_revert.py’

    – LisaD

    14/09/2016 a las 23:54

  • @Ness esto solo “des-migra”. Si ya no desea realizar esa migración, también debe eliminar el archivo de migración.

    – tocino dietético

    21 de marzo de 2017 a las 14:47

  • Siempre que utilice su nombre de migración real y no '0010_previous_migration'no sé por qué verías ese comportamiento.

    – Alasdair

    3 de julio de 2017 a las 19:02

  • Usando django 2.1, esto funciona para mí: /manage.py migrate my_app 0010solamente 0010, no el nombre completo del archivo. Después de eso, elimine manualmente los archivos locales appname/migrations/0011+, luego elimine manualmente las filas de la tabla db django_migrations para 0011+.

    – Emilio

    17 de marzo de 2019 a las 3:36

Avatar de usuario de AlanSE
AlanSE

La respuesta de Alasdair cubre lo básico.

  • Identifique las migraciones que desea por ./manage.py showmigrations
  • migrate usando el nombre de la aplicación y el nombre de la migración

Pero cabe señalar que no todas las migraciones pueden ser invertido. Esto sucede si Django no tiene una regla para hacer la inversión. Para la mayoría de los cambios que realizó migraciones automáticamente por ./manage.py makemigrations, la reversión será posible. Sin embargo, las secuencias de comandos personalizadas deberán tener escritos tanto hacia adelante como hacia atrás, como se describe en el ejemplo aquí:

https://docs.djangoproject.com/en/1.9/ref/migration-operations/

Cómo hacer una reversión sin operación

si tuvieras un RunPython operación, entonces tal vez solo desee revertir la migración sin escribir un script de reversión lógicamente riguroso. El siguiente truco rápido al ejemplo de los documentos (enlace anterior) permite esto, dejando la base de datos en el mismo estado que estaba después de que se aplicó la migración, incluso después de revertirla.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

def forwards_func(apps, schema_editor):
    # We get the model from the versioned app registry;
    # if we directly import it, it'll be the wrong version
    Country = apps.get_model("myapp", "Country")
    db_alias = schema_editor.connection.alias
    Country.objects.using(db_alias).bulk_create([
        Country(name="USA", code="us"),
        Country(name="France", code="fr"),
    ])

class Migration(migrations.Migration):

    dependencies = []

    operations = [
        migrations.RunPython(forwards_func, lambda apps, schema_editor: None),
    ]

Esto funciona para Django 1.8, 1.9


Actualización: una mejor manera de escribir esto sería reemplazar lambda apps, schema_editor: None con migrations.RunPython.noop en el fragmento de arriba. Ambos son funcionalmente lo mismo. (crédito a los comentarios)

  • Desde Django 1.8 en adelante, debe usar RunPython.noop en lugar de una lambda en línea o equivalente: docs.djangoproject.com/en/1.8/ref/migration-operations/…

    – CucharaMeiser

    10 oct 2016 a las 14:01


  • @SpoonMeiser En la sintaxis del ejemplo, creo que parece migrations.RunPython(forwards_func, migrations.RunPython.noop). Necesito verificar eso funcionalmente. Eso debería agregarse como una respuesta o una edición a esta en algún momento.

    – Alan SE

    10/10/2016 a las 17:48

Avatar de usuario de DanGoodrick
Dan Goodrick

No elimine el archivo de migración hasta después de la reversión. Cometí este error y sin el archivo de migración, la base de datos no sabía qué cosas eliminar.

python manage.py showmigrations
python manage.py migrate {app name from show migrations} {00##_migration file.py}

Si desea revertir todas las migracionesusar zero como el nombre de la migración:

python manage.py migrate app_name_here zero

Elimine el archivo de migración. Una vez que la migración deseada está en sus modelos…

python manage.py makemigrations
python manage.py migrate

Aquí está mi solución, ya que la solución anterior realmente no cubre el caso de uso, cuando usa RunPython.

Puede acceder a la tabla a través del ORM con

from django.db.migrations.recorder import MigrationRecorder

>>> MigrationRecorder.Migration.objects.all()
>>> MigrationRecorder.Migration.objects.latest('id')
Out[5]: <Migration: Migration 0050_auto_20170603_1814 for model>
>>> MigrationRecorder.Migration.objects.latest('id').delete()
Out[4]: (1, {u'migrations.Migration': 1})

Para que pueda consultar las tablas y eliminar aquellas entradas que sean relevantes para usted. De esta manera se puede modificar en detalle. Con RynPython migraciones, también debe cuidar los datos que se agregaron/cambiaron/eliminaron. El ejemplo anterior solo muestra cómo accede a la tabla a través de Djang ORM.

Hice esto en 1.9.1 (para eliminar la última o la última migración creada):

  1. rm <appname>/migrations/<migration #>*

    ejemplo: rm myapp/migrations/0011*

  2. inició sesión en la base de datos y ejecutó este SQL (postgres en este ejemplo)

    delete from django_migrations where name like '0011%';

Luego pude crear nuevas migraciones que comenzaron con el número de migración que acababa de eliminar (en este caso, 11).

  • +1 Aunque esto funcionará, debe guardar de esta manera como último recurso. También debe recordar editar/soltar columnas/tablas a las que contribuyó la migración problemática.

    – nehem

    23 de febrero de 2017 a las 2:05

  • buen punto: usé esto cuando creé una migración pero no ejecuté “./manage.py migrate” todavía

    – Mikee

    23 de febrero de 2017 a las 17:41

Avatar de usuario de Radwan Abu-Odeh
Radwan Abu Odeh

Para revertir una migración:

python manage.py migrate <APP_NAME> <MIGRATION_NUMBER_PREFIX>

MIGRATION_NUMBER_PREFIX es el prefijo numérico de la migración a la que desea volver, por ejemplo 0001 ir a 0001_initial.py migración. entonces puede eliminar esa migración.

Puedes usar zero como su número de migración para revertir todas las migraciones de una aplicación.

  • +1 Aunque esto funcionará, debe guardar de esta manera como último recurso. También debe recordar editar/soltar columnas/tablas a las que contribuyó la migración problemática.

    – nehem

    23 de febrero de 2017 a las 2:05

  • buen punto: usé esto cuando creé una migración pero no ejecuté “./manage.py migrate” todavía

    – Mikee

    23 de febrero de 2017 a las 17:41

La otra cosa que puede hacer es eliminar la tabla creada manualmente.

Junto con eso, deberá eliminar ese archivo de migración en particular. Además, tendrás que elimine esa entrada en particular en la tabla django-migrations(probablemente el último en su caso) que se correlaciona con esa migración en particular.

  • tenga cuidado en este caso: está obligado a verificar que db sea adecuado.

    – Sławomir Lenart

    10 mayo 2016 a las 15:25

  • Yo agregaría MUY cuidado. Podría romper muchas cosas en Postgres, por ejemplo, restricciones.

    – joedborg

    24 mayo 2016 a las 14:24

¿Ha sido útil esta solución?