﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
17838	prefetch_related fails for GenericForeignKeys when related object id is not a CharField/TextField	mkai	anonymous	"After a ton of debugging, I finally found the reason why my prefetching wasn't working. Here's a simple test case with the comments framework:

{{{
from django.contrib.comments.models import Comment
for c in Comment.objects.all().prefetch_related('content_object'):
...     print c.content_object
...
 
SELECT * FROM ""django_comments"" ORDER BY ""django_comments"".""submit_date"" ASC  [3.67ms]
SELECT * FROM ""django_content_type"" WHERE ""django_content_type"".""id"" = 15  [1.42ms]
SELECT * FROM ""items_item"" WHERE ""items_item"".""id"" IN (709, 79) ORDER BY ""items_item"".""created"" DESC  [2.48ms]
SELECT * FROM ""items_item"" WHERE ""items_item"".""id"" = 79  [0.79ms]
SELECT * FROM ""items_item"" WHERE ""items_item"".""id"" = 709  [1.00ms]
}}}

As you can see, it's doing the IN query, but then issues another query for each item. The ```object_pk``` field on ```Comment``` is a TextField, but the id field on ```Item``` is an IntegerField. This has the effect that the cache lookup no longer works. It looks up a tuple like ```(79, <class Item>)```, but the cache has a tuple like ```(u'79', <class Item>)``` set.

A quick fix is to simply convert the value to an int in contrib.contenttypes.generic.py:

{{{
def gfk_key(obj):
    ct_id = getattr(obj, ct_attname)
    if ct_id is None:
        return None
    else:
    	# QUICK FIX: convert to int to fix cache lookups
        # return (getattr(obj, self.fk_field),
        return (int(getattr(obj, self.fk_field)),
                self.get_content_type(id=ct_id,
                                      using=obj._state.db).model_class())
}}}

That is probably a very naive solution. Maybe one should check the type of the related object's field and then (safely) convert the value based on that?

"	Bug	closed	contrib.contenttypes	dev	Release blocker	fixed	prefetch_related		Accepted	1	0	0	0	0	0
