diff --git a/AUTHORS b/AUTHORS index 7a4faea532..d2b31ff19b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -149,6 +149,7 @@ answer newbie questions, and generally made Django that much better: Sung-Jin Hong Richard House Robert Rock Howard + Rob Hudson Jason Huggins Hyun Mi Ae Tom Insam diff --git a/django/contrib/contenttypes/management.py b/django/contrib/contenttypes/management.py index cb52e0805e..49083d6d5c 100644 --- a/django/contrib/contenttypes/management.py +++ b/django/contrib/contenttypes/management.py @@ -1,34 +1,43 @@ -""" -Creates content types for all installed models. -""" - +from django.contrib.contenttypes.models import ContentType from django.dispatch import dispatcher from django.db.models import get_apps, get_models, signals from django.utils.encoding import smart_unicode -def create_contenttypes(app, created_models, verbosity=2): - from django.contrib.contenttypes.models import ContentType +def update_contenttypes(app, created_models, verbosity=2): + """ + Creates content types for models in the given app, removing any model + entries that no longer have a matching model class. + """ ContentType.objects.clear_cache() + content_types = list(ContentType.objects.filter(app_label=app.__name__.split('.')[-2])) app_models = get_models(app) if not app_models: return for klass in app_models: opts = klass._meta try: - ContentType.objects.get(app_label=opts.app_label, - model=opts.object_name.lower()) + ct = ContentType.objects.get(app_label=opts.app_label, + model=opts.object_name.lower()) + content_types.remove(ct) except ContentType.DoesNotExist: ct = ContentType(name=smart_unicode(opts.verbose_name_raw), app_label=opts.app_label, model=opts.object_name.lower()) ct.save() if verbosity >= 2: print "Adding content type '%s | %s'" % (ct.app_label, ct.model) + # The presence of any remaining content types means the supplied app has an + # undefined model and can safely be removed, which cascades to also remove + # related permissions. + for ct in content_types: + if verbosity >= 2: + print "Deleting stale content type '%s | %s'" % (ct.app_label, ct.model) + ct.delete() -def create_all_contenttypes(verbosity=2): +def update_all_contenttypes(verbosity=2): for app in get_apps(): - create_contenttypes(app, None, verbosity) + update_contenttypes(app, None, verbosity) -dispatcher.connect(create_contenttypes, signal=signals.post_syncdb) +dispatcher.connect(update_contenttypes, signal=signals.post_syncdb) if __name__ == "__main__": - create_all_contenttypes() + update_all_contenttypes() diff --git a/django/contrib/contenttypes/models.py b/django/contrib/contenttypes/models.py index cda47a18aa..1413586254 100644 --- a/django/contrib/contenttypes/models.py +++ b/django/contrib/contenttypes/models.py @@ -25,7 +25,7 @@ class ContentTypeManager(models.Manager): """ Clear out the content-type cache. This needs to happen during database flushes to prevent caching of "stale" content type IDs (see - django.contrib.contenttypes.management.create_contenttypes for where + django.contrib.contenttypes.management.update_contenttypes for where this gets called). """ global CONTENT_TYPE_CACHE