pythondjangodjango-migrations

How to order migration files across different apps in django?


I am working on a django project. After some time, I wanted to refactor the code. I wanted to create a new app and move some of my models to that app. Here's an example:

Suppose I have an app named CategoryApp and two models in it named Product and Category.

class Category(models.Model):
    ...

class Product(models.Model):
    ...

After some time of coding, I realized that I need a separate app for Product. So, I created a new app named ProductApp. And copied the Product model from CategoryApp to ProductApp. I managed all the foreign keys and relationships appropriately.

Now, I need to create the migration files.

First of all, I created a migration file for the app ProductApp (python3 manage.py makemigrations ProductApp) that just creates a new table productapp_product in the database. The migration file is named 0001.py. I applied this migration and a new table is created.

Second, I created an empty migration file in the ProductApp (python3 manage.py makemigrations ProductApp --empty). The migration file is named 0002.py I modified the contents of the empty migration file to run SQL query to copy all the data from categoryapp_product table to productapp_product. I also added reverse_sql in case I need to reverse the migration. I applied this migration as well and all the data are copied to the new table.

Third, I deleted the Product model from CategoryApp and created a migration file for CategoryApp. The migration file is named 0002.py. I applied this migration and the old table is now deleted.

I pushed my code to github. I went to my VPS server and pulled the latest code. I ran the command pyrhon3 manage.py migrate hoping that everything will work.

Alas, I got an error saying that categoryapp_product does not exist while migrating ProductApp/migrations/0002.py. Django had migrated CategoryApp/migrations/0002.py before ProductApp/migrations/0002.py which caused the categoryapp_product table to be deleted before its data could be copied to productapp_product.

Is there a way to specify the order of migration files to be migrated across apps? Or, is there a way to add a migration file as a dependency to another migration file?

What is the solution to this problem?


Solution

  • Or, is there a way to add a migration file as a dependency to another migration file?

    Yes. Django's makemigrations command does this automatically for you whenever it is able to detect that one app depends on another, let's say because they're related through ForeignKey or similar.

    But you can of course also add dependencies manually if you like.

    Here's a legit example from makemigrations:

    # users/migrations/0001_initial.py
    class Migration(migrations.Migration):
    
        initial = True
    
        dependencies = [
            ('auth', '0012_alter_user_first_name_max_length'),
            ('organization', '0001_initial'),
        ]
    

    The dependency-list as you can see contains tuples, where the tuple contains the app name and the name of the migration. My User model declares a ForeignKey to a model in the Organization app, so Django creates this depedency automatically.

    All of the migrations listed in the dependency attribute has to complete before this one can be executed, and all of the operations (including dependencies) in those migrations also have to complete. That means you have to be mindful of not just circular imports, but also of circular migration dependencies.