Created
August 16, 2013 07:25
-
-
Save glasslion/6247958 to your computer and use it in GitHub Desktop.
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/ and justinfx's gist cache_generics.py :
https://gist.github.com/justinfx/3095246#file-cache_generics-py Su…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
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/ | |
and | |
justinfx's gist cache_generics.py : | |
https://gist.github.com/justinfx/3095246#file-cache_generics-py | |
Supports customized object_id_field and GenericForeignKey name. | |
''' | |
from operator import attrgetter | |
from django.contrib.contenttypes.models import ContentType | |
def cache_generic_content_types(queryset, object_id_field='object_id', content_type_fk='content_object'): | |
""" | |
Django does not support select_related on generic foreign key. Thus some | |
ORM actions may trigger N+M querys(N is item number of the queryset and | |
M is the item number of the content type). This function will cache content | |
and reduce N+M querys to 2 querys. | |
object_id_field: see https://docs.djangoproject.com/en/1.3/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericRelation | |
content_type_fk: the name of GenericForeignKey which linked to content type | |
""" | |
get_object_id = attrgetter(object_id_field) | |
generics = {} | |
for item in queryset: | |
if get_object_id(item) is not None: | |
generics.setdefault(item.content_type_id, set()).add(get_object_id(item)) | |
content_types = ContentType.objects.in_bulk(generics.keys()) | |
relations = {} | |
for ct, fk_list in generics.iteritems(): | |
ct_model = content_types[ct].model_class() | |
relations[ct] = ct_model.objects.in_bulk(list(fk_list)) | |
for item in queryset: | |
try: | |
cached_val = relations[item.content_type_id][get_object_id(item)] | |
except KeyError: | |
cached_val = None | |
setattr(item, '_%s_cache' % content_type_fk, cached_val) | |
return queryset |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment