Opened 4 years ago

Last modified 4 years ago

#31686 closed New feature

SQL migrations don't set default in database, but would be handy — at Version 1

Reported by: Rik Owned by: nobody
Component: Database layer (models, ORM) Version: 3.0
Severity: Normal Keywords: sql migrations default not null
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Rik)

When you create a model with a default value and you make migrations for it and migrate it, they the database schema won't have a default. For Django it doesn't matter because the default is on the model. However, if you want to execute the database migrations before you deploy the new code, the old code should not crash with the new database schema. If you add a column that is NOT NULL and you don't set a default value, then the old version of the code, that doesn't know about the new column, won't be able to add a new row because it doesn't provide a value for the new column that cannot be NULL. You'll get an SQL error saying the column cannot be null.

Data migrations don't fix this, they update existing rows, you still have the problem if the old version of the code tries to add a new row to the table with the new schema. To make the new table schema backwards compatible we need to set a default value on the new column. Or it should allow NULL values of course, but this is not always what you want.

I have found the location in the code where this should be fixed. This line in the code sets drop=True which drops the default value from a column. This seems to happen if the column type support default values and if there is a default value set on the model. So Django always gets rid of the default value in the database:

https://github.com/django/django/blob/678c8dfee458cda77fce0d1c127f1939dc134584/django/db/backends/base/schema.py#L489

It would be great if we can add a database settings where you can tell Django to also set the default in the database. Something like:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
        'SET_COLUMN_DEFAULTS': True
    }
}

Change History (1)

comment:1 by Rik, 4 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top