Django south migration, does not set a default value

I use south to port my django models. However, in the south there is an unpleasant mistake. It does not set default values ​​in Postgres databases. Example:

created_at = models.DateTimeField(default = datetime.now) tag_id = models.PositiveIntegerField(default = 0) 

The south will add these 2 fields to the database, but will not set their default values, which must be done manually.

Is there a patch for this error?

UPDATE I have already tried setting the default date using auto_now_add=True , but this also does not set default values. Adding null=True to the field adds a db.alter_column to the migration script created by the south. But this removes the NOT NULL , does not add a default value. Same for integer field

+10
python django django-south
source share
3 answers

This is not a mistake, in the south or elsewhere.

I think you are confused about how default values ​​work in Django. Django does not set default values ​​in the database schema. It applies them directly in Python when a new instance is created. You can verify this by running manage.py sqlall and see that the generated SQL does not contain default attributes.

+12
source share

If you automatically generate your migrations using:

 ./manage.py schemamigration app_name --auto 

Then you need to make a small change to the migration before you actually apply it. Go to the generated migration (something like app_name/migrations/000X__auto_add_field_foo.py should be called) and find the argument:

 keep_default=False 

in the db.add_column call. Just change this to:

 keep_default=True 

And now Django will apply your default value to the actual schema in addition to any existing lines. It would be great if the South had some kind of setting to generate this parameter as True by default, but not such luck. You will need to do this edit every time.

+22
source share

As mentioned in earlier answers, the default mechanism in django is implemented in the model class and is not related to south transitions.

Also, from south 0.8, the keep_default flag keep_default deprecated and will not add a default value to your model.

What I am doing to solve this problem is to write a custom migration to add a default value. You can do this by creating a separate data transfer :

 ./manage.py datamigration your_app_name migration_name 

and add the following line to the forwards function:

 orm.YourModel.objects.update(field_name = DEFAULT_VALUE) 

Alternatively, instead of creating a new migration, you can change the original migration:

  • add no_dry_run = True to the class itself (so that you will have access to ORM).
  • add orm.YourModel.objects.update(field_name = DEFAULT_VALUE) at the end of the forwards function.

This way you do not need to write backward migration, because you already have the original delete column.

+2
source share

All Articles