Opened 10 years ago
Closed 10 years ago
#26476 closed Bug (invalid)
Migration preserve_default does not works properly?
| Reported by: | madeng | Owned by: | nobody | 
|---|---|---|---|
| Component: | Migrations | Version: | 1.8 | 
| Severity: | Normal | Keywords: | preserve_default sqlmigrate | 
| Cc: | g.bottalico@… | Triage Stage: | Unreviewed | 
| Has patch: | no | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | no | UI/UX: | no | 
Description
Hi all, I'm using Django<1.9
When i change my model adding a default to one field or adding a new field to existing model with a default, and I launch:
./manage.py sqlmigrate my_app_label my_migration_name
I see:
BEGIN;
ALTER TABLE my_app_label ADD COLUMN my_char_field varchar(36) DEFAULT test NOT NULL;
ALTER TABLE my_app_label ALTER COLUMN my_char_field DROP DEFAULT;
COMMIT;
Reading Docs (https://docs.djangoproject.com/en/1.8/ref/migration-operations/#alterfield) i can see, about  that preserve_default, that :
The preserve_default argument indicates whether the field’s default value is permanent and should be baked into the project state (True), or if it is temporary and just for this migration (False) - usually because the migration is altering a nullable field to a non-nullable one and needs a default value to put into existing rows. It does not affect the behavior of setting defaults in the database directly - Django never sets database defaults and always applies them in the Django ORM code.
So why I see launching sqlmigrate DEFAULT and than DROP DEFAULT ?
For large databases this could be an heavy pair of query.
Best Regards
Change History (3)
comment:1 by , 10 years ago
| Summary: | Migration preserve_default does not work properly → Migration preserve_default does not works properly | 
|---|
comment:2 by , 10 years ago
| Summary: | Migration preserve_default does not works properly → Migration preserve_default does not works properly? | 
|---|
comment:3 by , 10 years ago
| Resolution: | → invalid | 
|---|---|
| Status: | new → closed | 
If table
my_app_labelis not empty when you run this migration, and you try to add a non-null column without a default, your database should give an error. This is why Django uses a default in the transaction.Your reading of the documentation is a bit too literal -- or, arguably, the documentation is not clear enough; what is meant is that Django never leaves defaults in the database.
Indeed, for large databases the aler-table queries (well, the first) could be quite heavy. I am not aware of a light way to add a non-nullable column to a large table.
In the future, please ask "is this a bug" type questions on a users' forum, such as the #django IRC channel or django-users mailing list.