7

i'm facing an issue with defaults values of tables.

for example i have this model:

class model1(models.Model):
        field1 = models.CharField(max_length=50, default='My Default Value 1',db_column='field1')
        field2 = models.CharField(max_length=10)

        class Meta:
            db_table = 'model1'

and the postgresql table is generated without the default:

mydb=# \d model1
                                Table "public.model1"
 Column |         Type          |                      Modifiers                      
--------+-----------------------+-----------------------------------------------------
 id     | integer               | not null default nextval('model1_id_seq'::regclass)
 field1 | character varying(50) | not null
 field2 | character varying(10) | not null
Indexes:
    "model1_pkey" PRIMARY KEY, btree (id)

the output of migrate sqlmigrate is:

CREATE TABLE "model1" ("id" serial NOT NULL PRIMARY KEY, "field1" varchar(50) NOT NULL, "field2" varchar(10) NOT NULL);
COMMIT;

but if i modify the default value in the model and run a makemigrations/migrate and after that i look into sqlmigrations the output genereates a weird DROP DEFAULT after creating

ALTER TABLE "model1" ALTER COLUMN "field1" SET DEFAULT 'My Default Value 1 modified';
ALTER TABLE "model1" ALTER COLUMN "field1" DROP DEFAULT;
COMMIT;

is there something I am missing or default values for columns are just not supported?

Cœur
  • 37,241
  • 25
  • 195
  • 267

2 Answers2

11

I know it's a bit late, but I was having the same issue. After searching extensively, i found this

"Django uses database defaults to set values on existing rows in a table. It doesn't leave the default values in the database so dropping the default is correct behavior."

https://code.djangoproject.com/ticket/28000

so it looks like this is simply how django has been designed. It bugged me, because when I then inserted data using MySQL, I was given warnings about having no default.

Sigh, I'm sure smarter people than me could come up with a good explanation as to why they've designed it like this.

rbennell
  • 1,134
  • 11
  • 14
2

I've ran in to similar issue: during deployment without downtimes database needs to support two versions of the model at the same time (old and new one) - so having a default value in the field in the database would be really great (the old model has no idea how to handle new fields).

Possible solutions:

1. Wait for Field.db_default mentioned in this ticket:

https://code.djangoproject.com/ticket/470 → This would be the best one!

2. Override the migration by using RunSQL

RunSQL(
  'ALTER TABLE model1 ADD COLUMN new_field1 BOOLEAN NOT NULL DEFAULT false',
  'ALTER TABLE model1 DROP COLUMN new_field1',
  state_operations=[
      migrations.AddField(
          model_name='model1',
          name='new_field1',
          field=models.BooleanField(default=False),
          preserve_default=True,
      ),
  ],
)

Please see https://pankrat.github.io/2015/django-migrations-without-downtimes/

3. Use django-add-default-value

https://github.com/3YOURMIND/django-add-default-value

(so far I'm using this option)