Django has the notion of a polymorphic foreign key (they call it a “generic relation”); that is, the ability to store a reference to a content item in any other table.
It does this via the contenttypes framework. The way it works is that every Django model has a content type, and this is stored alongside the foreign key so as to be able to resolve the key to the correct table. The content type is stored as an integer id.
I came across this recently whilst migrating comments from a different system into Django. Django’s comments use a generic relation so that you can comment on any object that has a Django model.
Constructing the SQL to migrate the comments, I found myself needing to look up these ids. I wasn’t able to google up an answer as to how to do this exactly so I thought it’d be worth blogging the solution.
The answer is that Django has a ContentTypes model, and hence a django_content_types table in the database. The id that is needed by Django’s comments app is the primary key of a row in this table corresponding to the type of item that the comment is about.
Django appears to allocate the content types on demand; thus, you may not see a row in this table for the specific content type you care about.
To get the content type id for a particular model, the code is:
from django.contrib.contenttypes.models import ContentType
from your.models import YourModel
id = ContentType.objects.get_for_model(YourModel).id
(This will magically add the content type if it doesn’t already exist.)