The problem may be caused by persistent generic relationships implemented by Django content types . Relations in Django are not only static, implemented by models and INSTALLED_APPS , but also dynamically implemented by the django_content_type table, which preserves the mapping from the numeric id to app_label + model. An example of a possible dynamic relationship is resolution or comment. You may or may not have permission to any table in any installed application. You can write a comment on everything, for example, on an article, on the user of the comment itself without changing any model. This relationship is implemented by storing the numerical identifier ContentType associated with this model (table) and the primary key of the associated object (row).
Django does not expect anyone to manipulate the database manually. If you use south for manipulation, then if you run syncdb after uninstalling the application, you will be asked south if you want to automatically remove spelling types. You can then safely delete unused tables without further reference.
(Possible hack: delete from django_content_type where app_label='social_auth' , but south delete from django_content_type where app_label='social_auth' .)
Many parts of the question are still open.
Edit :
Why this was wrong: all generic relationships from descendants to parents, and all data about the relationship is stored in the descendant. If the child application is removed from INSTALLED_APPS, then the django.db code can never try to remove the descendants, because it cannot recognize which columns contain this relationship.
source share