Django: find ghost tables without associated models

Who you gonna call? Ghost-table-busters!

Heavy refactoring of models can leave a Django project with “ghost tables”, which were created for a model that was removed without any trace in the migration history. Thankfully, by using some Django internals, you can find such tables.

Use the database introspection methods table_names() to list all tables and django_table_names() to list tables associated with models. By casting these to sets, you can subtract the latter from the former to find tables not associated with a model:

In [1]: from django.db import connection

In [2]: table_names = set(connection.introspection.table_names())

In [3]: django_table_names = set(connection.introspection.django_table_names())

In [4]: table_names - django_table_names - {"django_migrations"}
Out[4]:
{'sweetshop_humbug',
'sweetshop_jellybean',
'sweetshop_marshmallow'}

Note the django_migrations table needs excluding. This is Django’s internal table for tracking migrations, which has no associated (permanent) model.

From here, you’ll want to make a judgement call on what to do with the tables. Perhaps some should have models created whilst others can be removed.

To generate a model for a ghost table, use the inspectdb management command:

$ ./manage.py inspectdb sweetshop_humbug
# This is an auto-generated Django model module.
# ...
from django.db import models


class SweetshopHumbug(models.Model):
  id = models.BigAutoField(primary_key=True)
  ...

If a ghost table has no useful data or references in migrations, consider dropping it directly with SQL, rather than adding a migration. Make sure you have a backup, just in case! You can drop using dbshell. For example, using PostgreSQL:

$ ./manage.py dbshell
psql (...)
Type "help" for help.

candy=# DROP TABLE sweetshop_humbug;
DROP TABLE

Fin

May your database not be haunted by the ghosts of tickets past,

—Adam


Read my book Boost Your Django DX, freshly updated in November 2024.


Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: