What is Django ContentType

In this series, we will understand Django's ContentType and what is GenericForeignKey with examples. contenttypes is a Django app that can track all of the models installed in our Django-powered project, providing a high-level, generic interface for working with our models.

If we check in settings INSTALLED_APPS we can see, that django.contrib.contenttypes is readily present.

INSTALLED_APPS = [
    ...
    'django.contrib.contenttypes',
    ...
]

Since contenttypes is just like any other app, it also has migrations and, and views.py. The most important model of the contenttypes app is ContentType. Let's see what fields ContentType has.

class ContentType(models.Model):
    app_label = models.CharField(max_length=100)
    model = models.CharField(_('python model class name'), max_length=100)
    objects = ContentTypeManager()

    class Meta:
        verbose_name = _('content type')
        verbose_name_plural = _('content types')
        db_table = 'django_content_type'
        unique_together = [['app_label', 'model']]

    def __str__(self):
        return self.app_labeled_name

Apart from the custom manager, it has app_label and model both as string fields, which also are unique_together.

  • app_label is the name of the application the model is part of.
  • model is the name of the model itself.

We have already established that ContentType is a model that tracks all the models in your Django app and therefore, as soon as we create a new table in the database, a new entry gets created for the new table in the ContentType table. Consequently, ContentType model objects "points" to a particular table in your Django app. Let's see few entries in the ContentType table.

>>> from django.contrib.contenttypes.models import ContentType

>>> ContentType.objects.filter(model='user').values()
<QuerySet [{'id': 4, 'app_label': 'auth', 'model': 'user'}]>

>>> ContentType.objects.filter(model='contenttype').values()
<QuerySet [{'id': 5, 'app_label': 'contenttypes', 'model': 'contenttype'}]>

Since ContentType itself is a model, the ContentType model also tracks itself and thus has an entry for itself, this sounds a bit confusing but makes complete sense.

ContentType model has 2 important methods, model_class and get_object_for_this_type, let's see with an example what these methods do.

>>> from django.contrib.contenttypes.models import ContentType

>>> user_ct = ContentType.objects.get(model='user')
>>> user_ct.model_class()
django.contrib.auth.models.User

>>> user_ct.get_object_for_this_type(username='bob')
<User: bob>

Okay, so now at this point we know what ContentType is, but what good is it for? Why do we need this?

  • GenericForeignKeys are implemented via ContentType, we will see this in the next part of this article about how ContentTypes are used.
  • The admin application uses it to log the history of each object added or changed through the admin interface. Django’s authentication framework uses it to tie user permissions to specific models.
  • Since we have all models listed here in one place, we can use this to build generic solutions.

In this article, we understood about ContentType model and contenttypes framework, in the next article, we will see one of the implementations of ContentType which is GenericForeignKey.

17