python - sqlmigrate - Migraciones de django: flujo de trabajo con mĂșltiples ramas de desarrollo.
python manage py make migrations (2)
Tengo curiosidad por saber cómo otros desarrolladores de django administran múltiples ramas de código (en git, por ejemplo) con migraciones.
Mi problema es el siguiente: - tenemos varias sucursales de características en git, algunas de ellas con migraciones de django (algunas de ellas modificando campos o eliminándolas por completo) - cuando cambio de sucursales (con git checkout some_other_branch
), la base de datos no se refleja siempre El nuevo código, por lo que me encuentro con errores "aleatorios", donde ya no existe una columna de la tabla db, etc ...
En este momento, simplemente suelto el db y lo vuelvo a crear, pero eso significa que tengo que volver a crear un montón de datos ficticios para reiniciar el trabajo. Puedo usar accesorios, pero requiere un seguimiento de qué datos van a dónde, es un poco complicado.
¿Hay una forma buena / limpia de lidiar con este caso de uso? Estoy pensando que un script de git hook post-checkout
podría ejecutar las migraciones necesarias, pero ni siquiera sé si las reversiones de migración son posibles.
Las reversiones de las migraciones son posibles y generalmente son manejadas automáticamente por django.
Teniendo en cuenta el siguiente modelo:
class MyModel(models.Model):
pass
Si ejecuta python manage.py makemigrations myapp
, generará el script de migración inicial. Luego puede ejecutar python manage.py migrate myapp 0001
para aplicar esta migración inicial.
Si después de eso usted agrega un campo a su modelo:
class MyModel(models.Model):
my_field = models.CharField()
Luego, regenere una nueva migración y aplíquela, aún puede volver al estado inicial. Simplemente ejecute python manage.py migrate myapp 0001
y ORM retrocederá, eliminando el nuevo campo.
Es más complicado cuando se trata de migraciones de datos, ya que tiene que escribir el código de avance y retroceso. Teniendo en cuenta una migración vacía creada a través de python manage.py makemigrations myapp --empty
, terminarás con algo como:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
def forward(apps, schema_editor):
# load some data
MyModel = apps.get_model(''myapp'', ''MyModel'')
while condition:
instance = MyModel()
instance.save()
def backward(apps, schema_editor):
# delete previously loaded data
MyModel = apps.get_model(''myapp'', ''MyModel'')
while condition:
instance = MyModel.objects.get(myargs)
instance.delete()
class Migration(migrations.Migration):
dependencies = [
(''myapp'', ''0003_auto_20150918_1153''),
]
operations = [
migrations.RunPython(forward, backward),
]
Para migraciones de carga de datos puras, normalmente no necesita la migración hacia atrás. Pero cuando alteras el esquema y actualizas las filas existentes,
(como convertir todos los valores de una columna a slug), generalmente tendrás que escribir el paso hacia atrás.
En nuestro equipo, intentamos evitar trabajar en los mismos modelos al mismo tiempo para evitar colisiones. Si no es posible, y se crean dos migraciones con el mismo número (por ejemplo, 0002), aún puede cambiar el nombre de uno de ellos para cambiar el orden en el que se aplicarán (también recuerde actualizar el atributo de dependencies
en la clase de migración para tu nuevo pedido).
Si terminas trabajando en los mismos campos de modelo al mismo tiempo en diferentes características, aún estarás en problemas, pero puede significar que estas características están relacionadas y deben manejarse juntas en una sola rama.
Para la parte de git-hooks, probablemente sea posible escribir algo, asumiendo que estás en la rama mybranch
y quieres revisar otra característica de la rama myfeature
:
- Justo antes de cambiar, vuelca la lista de migraciones aplicadas actualmente en un archivo temporal
mybranch_database_state.txt
- A continuación, se aplican las
myfeature
ramamyfeature
, si las hay - Luego, al revisar
mybranch
,mybranch
a aplicar el estado de su base de datos anterior mirando el archivo de volcado.
Sin embargo, a mí me parece un poco malhumorado, y probablemente sería muy difícil manejar adecuadamente todos los escenarios: reorganización, fusión, selección de cerezas, etc.
Manejar los conflictos migratorios cuando ocurren me parece más fácil.
No tengo una buena solución para esto, pero siento el dolor.
Un gancho posterior a la salida será demasiado tarde. Si está en la sucursal A y verifica la sucursal B, y B tiene menos migraciones que A, la información de reversión solo está en A y debe ejecutarse antes de finalizar la compra.
Me topé con este problema cuando saltaba entre varios intentos intentando localizar el origen de un error. Nuestra base de datos (incluso en la versión de desarrollo) es enorme, por lo que no es práctico soltar y recrear.
Estoy imaginando una envoltura para git-checkout que:
- Toma nota de la migración más reciente para cada uno de tus INSTALLED_APPS
- Busca en la rama solicitada y toma nota de las migraciones más recientes allí.
- Para cada aplicación donde las migraciones en el # 1 están más adelantadas que en el # 2, vuelva a migrar a la migración más alta en el # 2
- Echa un vistazo a la nueva sucursal
- Para cada aplicación donde las migraciones en el # 2 fueron anteriores al # 1, migran hacia adelante
Una simple cuestión de programación!