Search code examples
pythondjangodatabasefieldnon-nullable

Django 1.7: Makemigration: non-nullable field


I am trying to use django-orderedmodel (https://github.com/kirelagin/django-orderedmodel) in my project.

Running makemigrations doesn't work:

 You are trying to add a non-nullable field 'order' to slide without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option: 

I would like to know where I'm doing this wrong. Thanks


Solution

  • As the order field is unique, you'll need to add the field in several migration steps, replacing the original operations in your migration:

    • Add a nullable field, set the default to NULL.
    • Set the field to a unique value in each row.
    • Add a NOT NULL constraint.

    I.e. something like this:

    operations = [
        migrations.AddField('myapp.MyModel', 'order', models.PositiveIntegerField(null=True, unique=True)),
        migrations.RunPython(set_order),
        migrations.AlterField('myapp.MyModel', 'order', models.PositiveIntegerField(blank=True, unique=True)),
    ]
    

    where set_order is a function that sets the order to a valid value, e.g.:

    def set_order(apps, schema_editor):
        MyModel = apps.get_model('myapp', 'MyModel')
        for i, model in enumerate(MyModel.objects.all()):
            model.order = i
            model.save()
    

    It's easiest to provide a default value (i.e. 0), and then replace the operations in the generated migration.