When duplicate tables are created during migrations, Django shows django.db.utils.ProgrammingError - Relation Already Exists
, blocking auto admin registration.
This error usually pops up when Django tries to create a database table (via migrate) that already exists in your database, but not in Django’s migration history.
In short: Django thinks the table doesn't exist, but the database knows it does.
Example:
You created a model like this:
class Post(models.Model):
title = models.CharField(max_length=100)
python manage.py makemigrations
python manage.py migrate
Common Causes
Here’s when I usually see this:
- You manually created tables in the DB (e.g., via PgAdmin or SQL).
- You deleted migrations but didn’t drop the database tables.
- You checked out a Git branch with old migrations and ran migrate.
- Your model class changed, but the migration state got out of sync.
- You ran migrate after copying a production DB without cleaning up.
Drop the Table (if you don’t need it)
If the table exists but has no important data yet:
PostgreSQL:
DROP TABLE blog_post;
python manage.py dbshell
python manage.py migrate
Fake the Migration (if the table is already in sync)
If the table should exist but the migration just isn’t aware of it:
python manage.py migrate your_app_name --fake
Reset Migrations (last resort)
If your migrations are a mess and you’re still in development:
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc" -delete
python manage.py makemigrations
python manage.py migrate --fake
Pro Tip: Use showmigrations
If you want to see what migrations Django thinks are applied:
python manage.py showmigrations
Related Fixes and Resources
- ✅ How to Build a Django Project Step-by-Step
- 🧱 Fixing 'no such table' errors in SQLite (coming soon)
- 🗂️ Understanding Django Migrations: A Beginner’s Guide (coming soon)
- 🔍 Add Search Functionality to Your Django Site
How to Prevent This in the Future
- Don’t delete migrations manually unless you reset the DB.
- Be cautious when switching branches with different migration states.
- Use --fake wisely, and only when DB and models match.
- If working in a team: sync migrations before committing new ones.
Final Thoughts
This error scared the heck out of me when I first saw it. But now I know: it’s just Django being cautious.
Once you understand how migrations work, these issues become easy to fix — and even easier to avoid.
Have you faced a weird Django error? Drop me a line