kebie
kebie

Reputation: 595

Django Update rows of enum tabel

Let's say that I have a enum table which looks like this (I know that it doesn't make any sense but it's not relevant for now :) ):

class Pet:
    ANIMALS = (
        ('D', 'Dog'),
        ('C', 'Cat'),
    )
    pet = models.CharField(primary_key=True, choices=ANIMALS)

    ...

And let's say that I've created some rows in another table which uses Pet class.

If at some point I decide that I need to change ('D', 'Dog') to ('S', 'Snake') will Django automatically detect rows that contain 'Dog' and update them?

Upvotes: 2

Views: 1274

Answers (2)

e4c5
e4c5

Reputation: 53774

First there are several issues with your model. It does not inherit from models.Model to begin with. And a 'choice' field isn't a good primary key candidate. If it were you could have only two records in your table. So your model should be

class Pet(models.Model):
    ANIMALS = (
        ('D', 'Dog'),
        ('C', 'Cat'),
    )
    pet = models.CharField(max_length=2, choices=ANIMALS)

And you are really better off with using an int here.

('D', 'Dog') to ('S', 'Snake') will Django automatically detect rows that contain 'Dog' and update them?

No. it will create a migration but that migration will not change the data. If you want to change the old data just type ./manage.py shell to open the console and then DO

 from myapp.models import Pet
Pet.objects.filter(pet='D').update(pet='S')

Note that looping through Pet.objects.all() and updating them one by one is not efficient.

Upvotes: 1

Joe Jasinski
Joe Jasinski

Reputation: 10801

Unfortunately, Django will not do that automatically. You'll need to define a database migration to alter the data in the pet column from "D" to "S".

Here is a direct link to that section of the docs: https://docs.djangoproject.com/en/1.9/topics/migrations/#data-migrations

Your use case is similar to the example that Django provides. In your migration file, you should be able to iterate through all of the Pet objects and change the pet attribute on each instance from "D" to "S".

Below is untested, but might be a starting point for making this change.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

def change_pet_key(apps, schema_editor):
    # We can't import the Pet model directly as it may be a newer
    # version than this migration expects. We use the historical version.
    Pet = apps.get_model("yourappname", "Pet")
    for pet in Pet.objects.all():
        pet.pet = 'S'
        pet.save()

class Migration(migrations.Migration):
    initial = True

    dependencies = [
        ('yourappname', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(change_pet_key),
    ]

Upvotes: 1

Related Questions