1

We use django 1.8 and migrations in our project and we run repeatedly into the following problem:

  1. We change/add a model with migration 1
  2. We add/change some data to satisfy new logic with migration 2
  3. We change again the model and create migration 3

Now one of the developers sync the 3 new migrations and encounters an error due to the mismatch between models.py and the database.

So far we have either faked the migrations which errors out or we changed dependencies ad hoc. This is neither systematic nor convenient though.

Is there any better way to approach the problem?

Following is a simple example of how the problem arise: original models.py

class Test(models.Model):
    a = models.CharField(max_length=200, verbose_name="A")
    b = models.CharField(max_length=200, verbose_name="B")

migrations before model change:

0001_initial.py

class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Test',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('a', models.CharField(max_length=200, verbose_name=b'A')),
                ('b', models.CharField(max_length=200, verbose_name=b'B')),
            ],
        ),
    ]

0002_auto_20160308_1103.py

def testData(apps, schema_editor):
    Test.objects.create(a="aaaa", b="bbb")
class Migration(migrations.Migration):

    dependencies = [
        ('Test', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(testData)
    ]

new models.py

class Test(models.Model):
    a = models.CharField(max_length=200, verbose_name="A")
    b = models.CharField(max_length=200, verbose_name="B")
    c = models.CharField(max_length=200, verbose_name="C", default="c")

last migration:

0003_test_c.py

class Migration(migrations.Migration):

    dependencies = [
        ('Test', '0002_auto_20160308_1103'),
    ]

    operations = [
        migrations.AddField(
            model_name='test',
            name='c',
            field=models.CharField(default=b'c', max_length=200, verbose_name=b'C'),
        ),
    ]

running migrate results in django.db.utils.OperationalError: table Test_test has no column named c while running the second migration.

2
  • This should never happen; migrations are meant for exactly this use case. Which means that you're doing something wrong. You should explain exactly what happens when you "encounter an error due to the mismatch". Commented Mar 8, 2016 at 10:47
  • amended the question with a reproducible example Commented Mar 8, 2016 at 11:12

1 Answer 1

3

You are not using the functionality that the migrations system provides. In particular, you're referencing the Test model directly; but the migrations system includes the concept of "historical models" which are built up dynamically from the migrations up to that point, which therefore solves this problem precisely.

The documentation explains this further, but basically instead of importing Test in migration 0002, you should get it dynamically:

def testData(apps, schema_editor):
    Test = apps.get_model("myapp", "Test")
    Test.objects.create(a="aaaa", b="bbb")
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! As always the answer is rtfm ... going to amend the question so that is easier for others to find it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.