Kit Fisto
Kit Fisto

Reputation: 4515

How to move Django model to other app with referencing foreign keys?

This is an extension to this question: How to move a model between two Django apps (Django 1.7)

I want to move a model M from an app A to app B using Django migrations without losing data. The best voted answer to the question (not the accepted one, the one by ozan) suggested usage of migrations.SeparateDatabaseAndState and doing it in two steps:

  1. Migration to delete the model and rename (not delete) the db table.
  2. Migration to create the new model and use the existing table for it.

This looks like a very clever way to me, however in my case there is another model N that has a foreign key to M. Now, when I call makemigrations to make the migration file in step two, I get an error because at that stage model A.M does no more exist:

ValueError: Lookup failed for model referenced by field C.N.m: A.M  

Is there a way to handle this?

Upvotes: 4

Views: 1874

Answers (2)

Kit Fisto
Kit Fisto

Reputation: 4515

This is how I finally did it. The main idea is doing the creation of the new model before the deletion of the old one as schillingt suggested, but also using migrations.SeparateDatabaseAndState to avoid database modifications as in the linked question.

  1. Copy the model from A to B. Define db_table to assign the same table name

  2. Make migrations for B. Modify the migration file to only create the state not the database table using migrations.SeparateDatabaseAndState.

  3. Modify the foreign key in N to point to B.M instead of A.M (via to='B.M').

  4. Make migration for this change.

  5. Delete model from A.

  6. Make migration for the deletion. Modify it such that it only deletes the model, not the database table.

  7. Apply all migrations.

One could still rename the table afterwards, however in the version 1.7 I use, migrations do not support db_table changes.

Upvotes: 6

schillingt
schillingt

Reputation: 13731

Here's how I would handle it.

  1. Create new model in app B (include 1:1Key to the model in app A), and migration and a new foreign key from model N to app B's model.
  2. Create migration to copy all the data from the old model in app A to the new model in app B.
  3. Populate the new FK on model N. You'll do this by using the 1:1Key between the models in apps A and B.
  4. Update all code and foreign keys to reference the new model in app B and run migrations.
  5. Remove FK from N to app A's model, and delete model from app A. Run the migration to remove them from the database.

Upvotes: 1

Related Questions