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?
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.