Saltar al contenido

¿Cómo forzar las migraciones a una base de datos si ya existen algunas tablas en Django?

Solución:

Cuando aplica una migración, Django inserta una fila en una tabla llamada django_migrations. Esa es la única forma en que Django sabe qué migraciones ya se han aplicado y cuáles no. Entonces, las filas de esa tabla deben coincidir con los archivos de su migrations directorio. Si ha perdido los archivos de migración después de su aplicación, o ha hecho algo más para desincronizar las cosas, tendrá problemas … porque los números de migración en su base de datos se refieren a archivos de migración diferentes a los de su proyecto.

Por lo tanto, antes de hacer cualquier otra cosa, debe volver a sincronizar las cosas eliminando el django_migrations filas de la tabla para cualquier archivo de migración que haya perdido de alguna manera y no pueda recuperar. La tabla debe contener filas solo para aquellas migraciones que tiene y que realmente se aplicaron a la base de datos correctamente.

Ahora debe lidiar con cualquier cambio en su base de datos que Django Migrations no conozca … y para eso hay algunas opciones:

Si las cosas funcionaron de tal manera que los cambios de la base de datos que ya se aplicaron a la base de datos están en archivos de migración diferentes a los que no lo estaban, entonces puede solucionarlo ejecutando sus migraciones una a la vez utilizando el --fake opción sobre cualquier cambio que en realidad ya esté en la base de datos. La opción falsa simplemente escribe la fila en el django_migrations tabla que marca la migración como realizada. Solo haga esto si la base de datos ya tiene todos los cambios contenidos en ese archivo de migración.

Y aquellos archivos de migración que contienen solo cambios que no se han aplicado a la base de datos, se ejecutan sin el --fake opción y Django los aplicará. p.ej:

# database already has it
manage.py migrate myapp 0003 --fake 
# need it
manage.py migrate myapp 0004
# database already has it
manage.py migrate myapp 0005 --fake

Si tiene archivos de migración en los que se han aplicado algunos de los cambios, pero no todos, entonces tiene un problema mayor. En ese caso, hay varias formas de hacerlo (elija SÓLO UNA):

  1. Edite los archivos de migración para colocar los cambios que ya se han aplicado (no importa si Django lo hizo o usted lo hizo manualmente) en migraciones de menor número, y coloque todo lo que necesita en archivos de mayor número. Ahora usted puede --fake los números más bajos y ejecute los números más altos como de costumbre. Digamos que tiene 10 cambios que hizo en sus modelos, y 5 de esos cambios ya están en la base de datos, pero Django no los conoce … así que cuando ejecute makemigrations, se crea una nueva migración con los 10 cambios. Esto normalmente fallará porque el servidor de la base de datos no puede, por ejemplo, agregar una columna que ya existe. Mueva estos cambios ya aplicados de su nuevo archivo de migración al archivo de migración anterior (ya aplicado). Django asumirá que estos se aplicaron con la migración anterior y no intentará volver a aplicarlos. Entonces puedes migrate como de costumbre y se aplicarán los nuevos cambios.

    Si no desea tocar su archivo de migración anterior, una forma más limpia de hacerlo es ejecutar primero makemigrations --empty appname para crear un archivo de migración vacío. Entonces corre makemigrations lo que creará otra migración con todos los cambios que Django cree que deben hacerse. Mueva las migraciones ya realizadas de ese archivo a la migración vacía que creó … luego --fake Aquél. Esto pondrá la comprensión de Django de cómo se ve la base de datos estará sincronizada con la realidad y luego podrá migrate normalmente, aplicando los cambios en el último archivo de migración.

  2. Deshágase de las nuevas migraciones que acaba de crear con makemigrations. Ahora, comente o vuelva a colocar cualquier cosa en sus modelos que no se haya aplicado a la base de datos, dejando que su código coincida con lo que realmente está en la base de datos. Ahora puedes hacer makemigrations y migrate appname --fake y volverás a sincronizar las cosas. Luego descomente su nuevo código y ejecute ‘makemigrations’ luego migrate como de costumbre y se aplicarán los cambios. Si los cambios son pequeños (por ejemplo, agregar algunos campos), a veces esto es más fácil. Si los cambios son grandes, no lo es …

  3. Puede continuar y (con cuidado) realizar los cambios en la base de datos usted mismo, actualizando la base de datos. Ahora solo corre migrate --fake y si no te equivocaste, todo estará bien. Nuevamente, esto es fácil para cambios más pequeños, no tan fácil para los complicados.

  4. Tu puedes correr manage.py sqlmigrate > mychanges.sql. Esto genera mychanges.sql que contiene todo el SQL que Django se hubiera ejecutado contra la base de datos. Ahora edite ese archivo para eliminar cualquier cambio que ya se haya aplicado, dejando lo que debe hacerse. Ejecute ese SQL usando pgadmin o psql (estás usando postgresql, espero). Ahora se han realizado todos los cambios … para que pueda ejecutar manage.py migrate --fake, esto sincronizará Django con la realidad y debería estar listo. Si sus conocimientos de SQL son suficientes, esta es probablemente la solución más sencilla.

Debo agregar dos advertencias:

Primero, si aplica una migración posterior, por ejemplo, 0003_foobar.py, y luego las cosas no funcionan y decide intentar volver atrás y aplicar 0002_bazbuz.py, entonces Django QUITARÁ COSAS DE SU BASE DE DATOS. Por ejemplo, una columna que podría haber agregado en 0003 se eliminará junto con sus datos. Dado que dice que no puede perder datos, tenga mucho cuidado al retroceder.

En segundo lugar, no se apresure a correr --fake migraciones. Asegúrese de que toda la migración que está a punto de falsificar ya esté en la base de datos. De lo contrario, se vuelve muy confuso. Si te arrepientes de las migraciones falsas y no quieres revertir, puedes borrar el conocimiento de django sobre la migración falsa eliminando esa fila del django_migrations mesa. Está bien hacer esto … si comprende lo que está haciendo. Si sabe que la migración realmente no se aplicó, entonces está bien.

Esta publicación de blog realmente lo clava. https://simpleisbetterthancomplex.com/tutorial/2016/07/26/how-to-reset-migrations.html

Permítanme resumir los pasos en su escenario 2 (tiene una base de datos de producción y desea cambiar el esquema / modelos en una o más aplicaciones). En mi caso, tenía dos aplicaciones, cola y deslizamiento de ruta, que tenían modificaciones de modelo que necesitaba aplicar a un sistema de producción. La clave era que ya tenía la base de datos, así que aquí es donde entra en juego –fake-initial.

Estos son los pasos que seguí. Como siempre, haga una copia de seguridad de todo antes de comenzar. Trabajo en una máquina virtual, así que tomé una instantánea antes de seguir adelante.

1) Elimine el historial de migración de cada aplicación.

python manage.py migrate --fake queue zero
python manage.py migrate --fake routingslip zero

2) Elimine los archivos de migración en todo el proyecto en el que residen las aplicaciones.

find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc"  -delete

3) Realizar migraciones

python manage.py makemigrations

4) Aplicar las migraciones, falsificando iniciales porque la base de datos ya existe y solo queremos los cambios:

python manage.py migrate --fake-initial

Funcionó muy bien para mí.

Comentarios y valoraciones del tutorial

Si te ha resultado de provecho este artículo, nos gustaría que lo compartas con otros juniors de esta forma contrubuyes a extender nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *