Steven Yong
Steven Yong

Reputation: 5446

Django migrations changing choices value

A field has been added to one of my MySQL table previously:

# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2017-09-14 00:49
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('my_app', '0102_previous_migrations'),
    ]

    operations = [
        migrations.AddField(
            model_name='my_client',
            name='my_team',
            field=models.CharField(choices=[('Unassigned', 'Unassigned'), ('ACT', 'ACT'), ('Korea', 'Korea'), ('National', 'National')], default='Unassigned', max_length=255, verbose_name='My Team'),
        ),
    ]

So users have a choices of the above selection in my UI and will be saved into the table my_client:

The changes have been deployed and now a beginner like me would like to change, i.e. remove Korea and add 2 new choices: NSW and SA

How would I go about this? Do I need another migration or I will just need to change those choices in the models?

I use this in my model now like this:

class Client(MyAppModel):
    TEAM_CHOICES = (
        ('Unassigned', 'Unassigned'),
        ('ACT', 'ACT'),
        ('Korea', 'Korea'),
        ('National', 'National'),
)

DEFAULT_TEAM = 'Unassigned'
my_team = models.CharField(verbose_name='MyTeam', null=False, max_length=255, choices=TEAM_CHOICES, default=DEFAULT_TEAM)

Update:

Base on the comment I have, I will need a migration too, a AlterField?

Do I also have to update all the existing value right now in the table my_client if any of them is having Korea to say Unassigned if I would like to remove Korea as a choice? What command can I use in the migration?

Upvotes: 8

Views: 7374

Answers (2)

Steven Yong
Steven Yong

Reputation: 5446

Figure this out later, hope it helps others beginner like me.

I have to update the Client model

class Client(MyAppModel):
    TEAM_CHOICES = (
        ('Unassigned', 'Unassigned'),
        ('National', 'National'),
        ('NSW', 'NSW'),
        ('SA', 'SA'),
)

Then enter this command:

python manage.py makemigrations

A migration will be generated:

from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('my_app', '0102_previous_migrations'),
    ]

    operations = [
        migrations.AlterField(
            model_name='my_client',
            name='my_team',
            field=models.CharField(choices=[('Unassigned', 'Unassigned'), ('ACT', 'ACT'), ('National', 'National'), ('NSW', 'NSW'), ('SA', 'SA')], default='Unassigned', max_length=255, verbose_name='My Team'),
        ),
    ]

Next to update all the existing values in the table now, referred here, enter this command to create an empty migration file:

python manage.py makemigrations --empty my_app

In the new migration file, put something like:

# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2017-10-26 06:36
from __future__ import unicode_literals

from django.db import migrations

def set_unassigned(apps, schema_editor):
    Client = apps.get_model('my_app', 'my_client')
    for client in Client.objects.all():
        client.account_team = 'Unassigned'
        client.save()

class Migration(migrations.Migration):

    dependencies = [
        ('my_app', '0104_client_team_update'),
    ]

    operations = [
        migrations.RunPython(set_unassigned),
    ]

Upvotes: 4

cdosborn
cdosborn

Reputation: 3459

A high-level approach:

Create a migration which only adds the new choice. Write a method to take all models with the old choice, and give them a proper new choice migration.RunPython. Create a migration which removes the old choice.

Upvotes: 4

Related Questions