preserve data while making changes to fields of model in django

I have two models which are Contact and UpdateInfo. Update model is a foreignkey relationship with Contact like below:

class Contacts(models.Model):
    full_name = models.CharField(max_length=100, blank=True)
    notes = RichTextField(blank=True)
    /............./

class UpdateInfo(models.Model):
    contacts = models.ForeignKey(Contacts,on_delete=models.CASCADE, related_name='update_info')
    updated_at = models.DateTimeField(auto_now=True)
    modified_by = models.CharField(max_length=100, blank=True)

Now what I need is to put the notes field into UpdateInfo model and remove from Contacts model. Because now the businees requirement has changed and what they need is they need to add notes in the existing notes and want to see them who added the notes and when they added it with the notes appended.

But the problem is if I remove the notes field from Contacts and add it to Updateinfo model , there are many data into the production and the notes field data will be lost.

Now how can we run migrate in such a way that I add notes field into the Updatinfo model and also migrating the data at the same time.?? Is this what is done by dev ops or we should do it?? Because usually dev ops are migrating the data to the production server from staging area.

I need expert opinion on this.


Solution 1:

You can create two migration files: 0002_add_notes_to_updateinfo.py and 0003_remove_notes_from_contact.py the first one will add the field to UpdateInfo model and then execute a function to migrate old data, after that in the second migration file you can remove the old field.

0002_add_notes_to_updateinfo.py:

from django.db import migrations

def migrate_old_data(apps, schema_editor):
    Contacts = apps.get_model('yourappname', 'Contacts')
    UpdateInfo = apps.get_model('yourappname', 'UpdateInfo')
    for contacts in Contacts.objects.all():
        UpdateInfo.objects.filter(contacts=contacts).update(notes=contacts.notes)
    

class Migration(migrations.Migration):

    dependencies = [
        #dependencies here,
    ]

    operations = [
        migrations.AddField(
            model_name='updateinfo',
            name='notes',
            field=RichTextField(blank=True),
            preserve_default=False,
        ),
        migrations.RunPython(migrate_old_data),
    ]

0003_remove_notes_from_contact.py:

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('yourapp', '0002_add_notes_to_updateinfo'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='contacts',
            name='notes',
        ),
    ]