19

I am writing a migration that requires me to fill a field with existing data from another field (with same type and constraints). Is it possible in Django to copy the data in a single operation? The destination column already exists when I need to copy the data.

In SQL, I would have written something like that:

UPDATE my_table SET column_b = column_a;

Edit

The current answer proposes to loop over the model instances, but that is what I want to avoid. Can it be done without a loop?

mimo
  • 2,469
  • 2
  • 28
  • 49
  • 1
    you can create a data migration [Data migrations](https://docs.djangoproject.com/en/1.10/howto/writing-migrations/) – rajeshcis Jan 06 '17 at 07:19

1 Answers1

32

As the comment mentioned, you can simply write a migration for this. I think the below should work though I haven't tested it. It uses the queryset update API and F to avoid looping

from __future__ import unicode_literals

from django.apps import apps
from django.db import migrations, models
from django.db.models import F


def copy_field(apps, schema):
    MyModel = apps.get_model('<your app>', 'MyModel')
    MyModel.objects.all().update(column_a=F('column_b'))


class Migration(migrations.Migration):
    dependencies = [
        ('<your app>', '<previous migration>'),
    ]

    operations = [
        migrations.RunPython(code=copy_field),
    ]
Bobort
  • 3,085
  • 32
  • 43
Rafi Goldfarb
  • 571
  • 4
  • 9
  • Maybe my question was not clear enough. I am indeed writing a migration. My actual question is: is it possible to avoid looping over the elements to copy the values. I know I can execute raw SQL from Django, but I wonder if there is no better way. – mimo Jan 06 '17 at 14:37
  • 1
    Revised my answer to avoid looping – Rafi Goldfarb Jan 06 '17 at 15:20
  • I cannot seem to create a field in the first operation, then use it in `copy_field` in a second operation. Can't we create a new field and copy to it from another, in a single migration? – Gauthier Feb 05 '21 at 15:27
  • Replying to myself: I've created two migrations to that effect. But copying the old field to the new one still doesn't work. I don't get the expression that looks like an assignment in `update()`. It seems to act like an assignment left-to-right, matching it to the original question. I can't make it work together with my interpretation of the doc. – Gauthier Feb 08 '21 at 15:00
  • 2
    Small update. `copy_field` needs two explicit parameters, so its more : `def copy_field(app, schema):` :) – Romain Apr 06 '21 at 16:06