template - django revierte la última migración
httpresponseredirect django parameters (7)
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})
Por lo tanto, puede consultar las tablas y eliminar las entradas que sean relevantes para usted.
De esta manera puede modificar en detalle.
Con
RynPython
migraciones de
RynPython
, 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.
He realizado 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? ¿Existe un comando para revertir la última migración y luego simplemente puedo eliminar el archivo de migración?
Esta respuesta es para casos similares si la respuesta principal de Alasdair no ayuda . (Por ejemplo, si la migración no deseada se crea pronto nuevamente con cada nueva migración o si se trata de una migración más grande que no se puede revertir o la tabla se ha eliminado manualmente).
... eliminar la migración, sin crear una nueva migración?
TL; DR : puede eliminar algunas migraciones revertidas (confusas) y hacer una nueva después de corregir los modelos . También puede usar otros métodos para configurarlo para que no cree una tabla mediante el comando migrate. La última migración debe crearse para que coincida con los modelos actuales .
Casos por los cuales alguien no quiere crear una tabla para un Modelo que debe existir:
A) No debería existir tal tabla en ninguna base de datos en ninguna máquina y sin condiciones
- Cuándo: es un modelo base creado solo para la herencia del modelo de otro modelo.
-
Solución:
Establecer
class Meta: abstract = True
B) La tabla se crea raramente, por otra cosa o manualmente de una manera especial.
-
Solución:
use la
class Meta: managed = False
La migración se crea, pero nunca se usa, solo en pruebas. El archivo de migración es importante, de lo contrario las pruebas de la base de datos no pueden ejecutarse, comenzando desde el estado inicial reproducible.
C) La tabla se usa solo en algunas máquinas (por ejemplo, en desarrollo).
-
Solución:
mueva el modelo a una nueva aplicación que se agregue a INSTALLED_APPS solo en condiciones especiales o use una
class Meta: managed = some_switch
condicionalclass Meta: managed = some_switch
.
D)
El proyecto utiliza múltiples bases de datos en la
settings.DATABASES
-
Solución:
escriba un
enrutador de base de datos
con el método
allow_migrate
para diferenciar las bases de datos donde se debe crear la tabla y dónde no.
La migración se crea en todos los casos A), B), C), D) con Django 1.9+ (y solo en los casos B, C, D con Django 1.8), pero se aplica a la base de datos solo en los casos apropiados o tal vez nunca si requerido así. Las migraciones han sido necesarias para ejecutar pruebas desde Django 1.8. Las migraciones registran el estado actual relevante completo, incluso para modelos con Managed = False en Django 1.9+ para que sea posible crear una ForeignKey entre modelos administrados / no administrados o para que el modelo sea administrado = True más adelante. (Esta pregunta se ha escrito en el momento de Django 1.8. Todo aquí debería ser válido para versiones entre la 1.8 y la 2.2 actual).
Si la última migración es (no) es fácilmente reversible, entonces es posible realizar con cautela (después de la copia de seguridad de la base de datos) una
reversión falsa
./manage.py migrate --fake my_app 0010_previous_migration
, elimine la tabla manualmente.
Si es necesario, cree una migración fija desde el modelo fijo y aplíquela sin cambiar la estructura de la base de datos
./manage.py migrate --fake my_app 0011_fixed_migration
.
Hice esto en 1.9.1 (para eliminar la última o la última migración creada):
-
rm <appname>/migrations/<migration #>*
ejemplo:
rm myapp/migrations/0011*
-
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).
La otra cosa que puede hacer es eliminar la tabla creada manualmente.
Junto con eso, tendrá que eliminar ese archivo de migración en particular. Además, deberá eliminar esa entrada en particular en la tabla django-migrations (probablemente la última en su caso) que se correlaciona con esa migración en particular.
La respuesta de Alasdair cubre los conceptos básicos.
-
Identifique las migraciones que desea mediante
./manage.py showmigrations
-
migrate
usando el nombre de la aplicación y el nombre de la migración
Pero debe señalarse que no todas las migraciones
pueden
revertirse.
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 mediante
./manage.py makemigrations
, la reversión será posible.
Sin embargo, las secuencias de comandos personalizadas deberán tener una escritura tanto directa como inversa, como se describe en el ejemplo aquí:
https://docs.djangoproject.com/en/1.9/ref/migration-operations/
Cómo hacer una inversión sin operación
Si tuvo una operación
RunPython
, entonces tal vez solo quiera retroceder la migración sin escribir un script de inversión lógicamente riguroso.
El siguiente truco rápido para el ejemplo de los documentos (enlace anterior) permite esto, dejando la base de datos en el mismo estado que tenía después de que se aplicara 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 las
lambda apps, schema_editor: None
con
migrations.RunPython.noop
en el fragmento anterior.
Ambos son funcionalmente la misma cosa.
(crédito a los comentarios)
Puede revertir 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
Luego 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
Si tiene problemas al revertir la migración, y de alguna manera lo ha desordenado, puede realizar migraciones
fake
.
./manage.py migrate <name> --ignore-ghost-migrations --merge --fake
Para la
versión django <1.7
esto creará una entrada en la tabla
south_migrationhistory
, debe eliminar esa entrada.
Ahora podrá revertir la migración fácilmente.
PD: Estuve atrapado durante mucho tiempo y realizar una migración falsa y luego volver atrás me ayudó.