Home > Back-end >  Unable to apply migration on altered model in django
Unable to apply migration on altered model in django

Time:01-13

I am new to django. I have changed some fields in my already created Django model. But It says this message when I try to apply migrations on it:

It is impossible to add a non-nullable field 'name' to table_name without specifying a default. This is because 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 with a null value for this column)
 2) Quit and manually define a default value in models.py.

Although I have deleted the data of this table from database. I cannot set it's default value because the field has to store unique values. Do I need to delete my previous migration file related to that table?

I have applied data migrations, but still getting the same error when applying migrations again:

def add_name_and_teacher(apps, schema_editor):
    Student = apps.get_model('app_name', 'Student')
    Teacher = apps.get_model('app_name', 'Teacher')
    for student in Student.objects.all():
        student.name = 'name'
        student.teacher = Teacher.objects.get(id=1)
        student.save()

class Migration(migrations.Migration):

    dependencies = [
        ('app', '0045_standup_standupupdate'),
    ]

    operations = [
        migrations.RunPython(add_name_and_teacher),
    ]

CodePudding user response:

So, before you had a nullable field "name". This means that it's possible to have null set as that field's value.

If you add a not null constraint to that field (null=False), and you run the migrations, you will get an integrity error from the database because there are rows in that table that have null set as that field's value.

In case you just made two migrations where first you added a nullable field, but then remembered it mustn't be nullable and you added the not null constraint, you should simply revert your migrations and delete the previous migration. It's the cleanest solution.

You can revert by running python manage.py migrate <app name> <the migration that you want to keep>

Then you simply delete the new migrations and run python manage.py makemigrations again.

In case the migration with the nullable field was defined very early on and there is already data there and it's impossible to delete that migration, you will need to figure out how to populate that data. Since you say that there is also the unique constraint, you can't just provide a default because it will cause issues with that constraint.

My suggestion is to edit the migration file and add migrations.RunSQL where you write custom SQL code which will insert values to the field. Make sure you place the RunSQL operation before the operation that adds the not null constraint (it should be AlterField or AddConstraint) as they are run in order.

You could also use migrations.RunPython, but I prefer the RunSQL because future changes in the code might break your migrations which is a hassle to deal with.

Docs for RunSQL

CodePudding user response:

It does not matter if you clear data from the table, because if the table exists for the model, this message will be the default response for Django models. You can either add the field in the model manually and fake the migration. Or you can consider putting default value in the migrations (just like prompt said). Putting a default value does not mean it will apply the default value in the table for new entries. This value will only be used when it updates existing rows in a table during migration, to make the process easier.

Apart from that, you can consider looking into data migration which will create empty migration files, where you can do whatever changes you want to the data (for example generate new names for the field).

  • Related