Django Generic Relation fields with get_object_or_404 shortcut
Jul 17th, 2009 by diegobz
Those days me and Ignacio were investigating a weird slowness in a feature of Transifex at http://transifex.net. For some reason there was a query that was taking so long to return the result and we were wondering why?
That was the query:
pofile = get_object_or_404(POFile, component=component, filename=filename)
This query intents to find a PO file with a specific name for a component. Component in this case, in the POFile model, is a generic relation that can be pointed to any object. It is not just a foreignkey to the Component model. Other models can be pointed there too.
The truth here is that, the POFile model does not have a ‘component’ field. It has two others fields instead, called ‘object_id’ and ‘content_type’. Django does a kind of magic and can discover that the ‘component’ field does exist and then relate it to the generic relation present in the model.
That’s really cool, but in the other hand it takes a lot of time. We got the same result using a more specific query and it brought a real gain of performance.
from django.contrib.contenttypes.models import ContentType
ctype = ContentType.objects.get_for_model(component)
pofile = get_object_or_404(POFile, object_id=component.pk, content_type=ctype, filename=filename)
Diego could you try this instead and see what happens (I don’t have a working tx instance):
pofile = get_object_or_404(component.pofiles, filename=filename)
@Christos
Good point. Looks like it works well too.