'''
Cache the generic relation field of all the objects
in the queryset, using larger bulk queries ahead of time.
Improved from original by Daniel Roseman:
http://blog.roseman.org.uk/2010/02/22/django-patterns-part-4-forwards-generic-relations/
Adapted for egonomy project by Thibaut Cavalie
'''
from django.contrib.contenttypes.models import ContentType
import logging
logger = logging.getLogger(__name__)
def cache_generics(queryset):
generics = {}
for item in queryset:
if item.object_id is not None:
generics.setdefault(item.content_type_id, set()).add(item.object_id)
content_types = ContentType.objects.in_bulk(generics.keys())
relations = {}
for ct, fk_list in generics.iteritems():
ct_model = content_types[ct].model_class()
# In our case relations[ct] = ct_model.objects.in_bulk(list(fk_list))
# is not enough because we need select_related for both images and fragments.
# We test str(content_types[ct])=="fragment" because it avoids import Image and Fragment just to test contenttypes.
# So we can import this function in models.py.
if str(content_types[ct]) == "image":
relations[ct] = ct_model.objects.select_related('info', 'metadata').in_bulk(list(fk_list))
elif str(content_types[ct]) == "fragment":
relations[ct] = ct_model.objects.select_related('image', 'image__info', 'image__metadata','author').in_bulk(list(fk_list))
else:
relations[ct] = ct_model.objects.in_bulk(list(fk_list))
for item in queryset:
try:
try:
item.object_id = int(item.object_id)
except:
pass
cached_val = relations[item.content_type_id][item.object_id]
except KeyError:
cached_val = None
setattr(item, '_content_object_cache', cached_val)