Il rollback delle migrazioni è possibile e generalmente gestito automaticamente da Django.
Considerando il seguente modello:
class MyModel(models.Model):
pass
Se si esegue python manage.py makemigrations myapp
, genererà lo script di migrazione iniziale. È possibile eseguire python manage.py migrate myapp 0001
per applicare questa migrazione iniziale.
Se dopo che si aggiunge un campo al modello:
class MyModel(models.Model):
my_field = models.CharField()
rigenerare una nuova migrazione, e applicarlo, è ancora possibile tornare allo stato iniziale. Basta eseguire python manage.py migrate myapp 0001
e l'ORM andrà indietro, rimuovendo il nuovo campo.
È più difficile quando si gestiscono le migrazioni dei dati, perché è necessario scrivere il codice forward e backward. Considerando una migrazione vuoto creato tramite python manage.py makemigrations myapp --empty
, vi ritroverete con qualcosa di simile:
# -*- 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),
]
per Pure migrazioni di caricamento dei dati, di solito non è necessario la migrazione a ritroso. Ma quando si modifica lo schema e si aggiornano le righe esistenti,
(come la conversione di tutti i valori in una colonna in slug), in genere è necessario scrivere il passaggio all'indietro.
Nel nostro team, cerchiamo di evitare di lavorare sugli stessi modelli allo stesso tempo per evitare collisioni. Se non è possibile, e si creano due migrazioni con lo stesso numero (es. 0002), è ancora possibile rinominare uno di questi per modificare l'ordine in cui verranno applicati (ricordarsi anche di aggiornare l'attributo sul classe di migrazione al tuo nuovo ordine).
Se si finisce per lavorare sugli stessi campi del modello allo stesso tempo nelle caratteristiche diverse, sarete comunque in difficoltà, ma può significa queste caratteristiche sono correlate e devono essere maneggiati insieme in un unico ramo.
Per la parte git-ganci, è probabilmente possibile scrivere qualcosa, supponendo che il sono sul ramo mybranch
e voler controllare un altro ramo caratteristica myfeature
:
- Poco prima di passare, si discarica l'elenco dei attualmente migrazioni applicata in un file temporaneo
mybranch_database_state.txt
- Quindi, si applica
myfeature
migrazioni filiali, se del caso
- Poi, quando il controllo indietro
mybranch
, si riapplica la tua precedente stato del database guardando al file di dettagli.
Tuttavia, sembra un po 'hacker per me, e probabilmente sarebbe davvero difficile da gestire correttamente tutti gli scenari: rebasing, la fusione, cherry-picking, ecc
Gestione dei conflitti migrazioni quando sembra mi sembra più facile.
Penso che @ eliot-berriot copra la maggior parte degli scenari. In realtà mi sono ispirato a questo numero per scrivere questo articolo in cui suggerisco una proposta: [Cosa mi infastidisce davvero delle migrazioni di Django] (https://cheesecakelabs.com/blog/really-annoys-django-migrations/?utm_source=stackoverflow&utm_medium= bernardo-domanda & utm_campaign = blog% 20 & utm_content = what-davvero-infastidisce-me-about-django-migrazioni). E ha iniziato questa lib con una proposta di hook git post-checkout: [django-nomad] (https://github.com/CheesecakeLabs/django-nomad). Cosa ne pensi? – bsmaniotto