Search code examples
pythondjangodjango-modelsdjango-migrations

Handling data during django migrations?


class Material(models.Model):
    name = models.CharField(max_length=50, blank=False)
    short_name = models.CharField(max_length=2, blank=False, unique=False, default='Al')
   
    def __str__(self):
        return self.name

    class Meta:
        db_table = 'material'

I have created this model. Let suppose I have added a new field called

status = models.IntergerField(default=1)

After that If I run command python manage.py makemigrations, then django will add a new field status in table. Let's I have 3 rows in the table, then value will be as below:

1. Material1, M1, 1
2. Material2, M2,1
3. Material3, M3, 1

With this migration, I also want to change the status of every row and add new row also like

1. Material1, M1, 1
2. Material2, M2,0
3. Material3, M3, 0
4. Material4, M4, 1

Is there any way to handle data manipulation along the schema migration in django?


Solution

  • You can set individual value by using Special Operations such as django.db.migrations.RunPython.

    (ref: https://docs.djangoproject.com/en/3.1/ref/migration-operations/#runpython)

    Suppose you have added a field 'status' to the model and have already completed making the migration(executing manage.py makemigrations).

    Now, execute manage.py makemigrations your_app --empty. Then, edit the auto-created migration file like below.

    from django.db import migrations
    
    
    def set_individual_status(apps, schema_editor):
        Material = apps.get_model("your_app", "Material")
    
        material_ids_status_0 = [2, 3]
        material_ids_status_1 = [1, 4]
    
        Material.objects.filter(id__in=material_ids_status_0).update(status=0)
        Material.objects.filter(id__in=material_ids_status_1).update(status=1)
    
    
    class Migration(migrations.Migration):
    
        dependencies = [("your_app", "00xx_auto_20210106_1527")]
    
        operations = [
            migrations.RunPython(set_individual_status, migrations.RunPython.noop)
        ]
    

    And then, execute manage.py migrate.