I have a model Car
with a CharField color
, that has the choices of white
, black
and blue
.
class Car(models.Model):
WHITE = "White"
BLACK = "Black"
BLUE = "Blue"
COLOR_CHOICES = (
(WHITE, "White"),
(BLACK, "Black"),
(BLUE, "Blue"),
)
...
color = models.CharField(max_length=20, choices=COLOR_CHOICES, default=BLUE)
I already have created Car
objects with a color. Now when I introduce a change to the choices (e.g. change BLUE to RED in all occurences, as well as in the default) and run the migrations, the Car
objects of color BLUE that already exist do not get migrated to RED. And that's where the weirdness begins:
Questions:
I expect upon migration all existing Car.BLUE objects to migrate to Car.RED when I run the migrations, because this is the new default value. I tried to manually create a new object and it picks up the new default RED color. I also tried to manually change an existing object from BLUE to RED, which is also fine. There were no errors when applying the migrations.
Django version - 4.1.5 DB - PostgreSQL
Django will make migrations if you change the choices=…
parameter [Django-doc], in fact Django will make a migration if you change any parameter. But the default migration handler… will not do anything when you change the choices
. One can implement a different handler, but likely it is not worth the effort.
This thus means that eventually no database changes will be done, so we will have to do this ourselves. If you want to modify data, you can make a data migration [Django-doc]. A data migration is just like a normal migration, except that we write how the database should change.
We make a data migration with:
python manage.py makemigrations --empty app_name
In the migration file, we can then construct an update query:
from django.db import migrations
def red_to_blue(apps, schema_editor):
Car = apps.get_model('app_name', 'Car')
Car.objects.filter(color='Red').update(color='Blue')
class Migration(migrations.Migration):
dependencies = [
("app_name", "1234_some_migration"),
]
operations = [
migrations.RunPython(red_to_blue),
]
If we then migrate, it will run the red_to_blue
function, and migrate the data in the database.