How I Moved Django Models Between Apps Without Losing Data
🚀 Introduction
In a recent project, I encountered a common yet sensitive challenge: migrating Django models from one application to another during a major codebase restructure, without losing any data.
If you’ve ever dealt with Django migrations, you’ll know that messing with app structure can quickly lead to broken migrations or worse — data loss.
In this post, I’ll walk you through the 9-step strategy I used to safely move models between Django apps. No hacks. No raw SQL. Just careful use of Django's migration system.
🏗️ Problem
We needed to move several models from one Django app to another as part of a domain reorganization effort. But these models had already been in production, holding critical data.
That meant:
✅ Solution Overview
The solution was split into two iterations:
🔄 First Iteration: Safe Transfer of Code
1. Move the Models to the New App
Move the model code from the original app to the new app’s models.py.
✅ Tip: Don’t remove the models from the old app just yet, we’ll deal with that shortly.
2. Add Meta.db_table to Preserve Table Names
In the new app, update each model with its original database table name:
class MyModel(models.Model):
...
class Meta:
db_table = 'original_table_name'
This ensures Django will not attempt to create a new table.
3. Create Migrations in Both Apps
Run:
python manage.py makemigrations old_app
python manage.py makemigrations new_app
This will generate a set of migrations, one removing models from the old app and one adding them to the new app.
4. Use SeparateDatabaseAndState
Now, edit both migration files to use Django's SeparateDatabaseAndState so that only Django’s model state changes, not the actual DB schema.
from django.db.migrations.operations.special import SeparateDatabaseAndState
operations = [
SeparateDatabaseAndState(
database_operations=[],
state_operations=[
migrations.CreateModel(...), # or DeleteModel for old app
]
)
]
This tells Django: “Update the Python model history, but leave the database tables untouched.”
5. Comment Out Delete Operations in Old App
In the old app’s migration, find and comment out any DeleteModel operations, just to be extra safe.
6. Apply the Migrations
Once both migration files are ready and safe, apply them:
python manage.py migrate
Your models are now officially moved — at least in Django’s eyes — while the database remains stable and intact.
🔁 Second Iteration — Finalizing the Move
7. Remove Meta.db_table
Once Django knows the models "belong" to the new app, you can safely remove the db_table overrides.
class MyModel(models.Model):
...
class Meta:
pass # or delete the Meta class entirely if not needed
8. Create New Migrations
Generate a fresh migration in the new app:
python manage.py makemigrations new_app
This migration tells Django to stop overriding the DB table name and use the default.
9. Run Final Migration
Apply the last migration:
python manage.py migrate
That’s it. The models now fully belong to the new app, and all data is intact.
🧠 Lessons Learned
💬 Conclusion
Moving models between Django apps isn't something you do every day, but when you do, doing it safely is critical.
By splitting the process into two controlled iterations and leveraging Django’s migration tools properly, I was able to restructure the project without data loss or migration corruption.
Associate Software Engineer @ Tkxel | Python | React | Full-Stack Developer
1moHelpful insight, Osama
SWE Intern @ Reka Studios | PUCIT'27 | Data Enthusiast | Python | C++ | Machine Learning | SQL | Streamlit | JavaScript (React) || AI enthusiast
1moInformative.
Software Engineer @ Devsinc | I build scalable software solutions |
1moInsightful, thanks for sharing Osama.
Software engineer (.NET Azure) || .NET || React js || Azure Integrations || Azure Devops || Microsoft Dynamic 365 CRM || Power Platform
1moWorth read.