Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to migrate data from a field to another in a table using south

Im working on a Django project using south for schema migrations. I have the following scenario:

schema

class Book(model.Models):
    name = models.CharField(max_length=255, blank=True)
    bid = models.IntegerField(blank=True, null=True)

class Author(model.Models):
   name = models.CharField(max_length=255, blank=True)
   book_id = models.ForeignKey(Book, null=True, to_field="bid", db_column="bookID")

I wanna change Author model to the following:

class Author(model.Models):
   name = models.CharField(max_length=255, blank=True)
   book = models.ForeignKey(Book, null=True, db_column="book_id")

but without loose data. I want to search each book by its bid and assign the one found to the new field in Author model.

Thanks

like image 520
Ernesto Avatar asked Oct 01 '22 20:10

Ernesto


1 Answers

You'll have to do a 3 migrations. A schemamgiration that adds the new book FK, then a data migration and then a schemamigration to delete and rename the fields.

So you'll want to change your models.py file to this:

class Book(model.Models):
    name = models.CharField(max_length=255, blank=True)
    bid = models.IntegerField(blank=True, null=True)

class Author(model.Models):
   name = models.CharField(max_length=255, blank=True)
   book_id = models.ForeignKey(Book, null=True, to_field="bid", db_column="bookID")
   # You don't need the db_column="book_id" since that's what it does at the DB level by default.
   # I'm not sure if things will break if you name it book with another field as book_id.
   book_new = models.ForeignKey(Book, null=True) 

Then run python manage.py schemamigration APP_NAME auto Then run ```python manage.py datamigration APP_NAME populate_book_id

Then edit the newly created data migration and loop through the Author instances setting the new book field with the book_id field. Don't forget to remove the book field values in the backwards method.

Then change your models.py file to the following:

class Book(model.Models):
    name = models.CharField(max_length=255, blank=True)
    bid = models.IntegerField(blank=True, null=True)

class Author(model.Models):
   name = models.CharField(max_length=255, blank=True)
   # You don't need the db_column="book_id" since that's what it does at the DB level by default.
   book = models.ForeignKey(Book, null=True) 

Then run python manage.py schemamigration APP_NAME auto You'll want to check this last schemamigration to make sure it's renaming book_new to book and not dropping and creating columns. Here's an answer that explains how to change it.

like image 100
schillingt Avatar answered Nov 01 '22 12:11

schillingt