Skip to content

Instantly share code, notes, and snippets.

@numan
Last active May 17, 2016 21:00
Show Gist options
  • Save numan/6097492 to your computer and use it in GitHub Desktop.
Save numan/6097492 to your computer and use it in GitHub Desktop.
Custom model resource for caching django-tastypie responses with django-cache-machine
from caching.invalidation import make_key
from functools import partial
def get_response_key(request):
smooshed = []
cache_keys = request.GET.keys()
cache_keys.sort()
for key in cache_keys:
smooshed.append(u"{}={}".format(key, request.GET[key]))
smooshed.append(u"HTTP_ACCEPT={}".format(request.META["HTTP_ACCEPT"]))
return make_key(u'api:v1:{}:{}'.format(request.path, smooshed), with_locale=False)
def get_response_key(request):
"""
Generate a unique key for each request.
"""
smooshed = []
cache_keys = request.GET.keys()
cache_keys.sort()
for key in cache_keys:
smooshed.append(u"{}={}".format(key, request.GET[key]))
smooshed.append(u"HTTP_ACCEPT={}".format(request.META["HTTP_ACCEPT"]))
return make_key(u'api:{}:{}'.format(request.path, smooshed), with_locale=False)
class CachingModelResource(ModelResource):
def create_cached_response(self, request, data, response_class=HttpResponse, **response_kwargs):
"""
Like ``create_response`` but assumes the data has already been serialized
"""
desired_format = self.determine_format(request)
return response_class(content=data, content_type=build_content_type(desired_format), **response_kwargs)
def create_response_content(self, to_be_serialized=None, request=None):
# Dehydrate the bundles in preparation for serialization.
bundles = []
for obj in to_be_serialized[self._meta.collection_name]:
bundle = self.build_bundle(obj=obj, request=request)
bundles.append(self.full_dehydrate(bundle, for_list=True))
to_be_serialized[self._meta.collection_name] = bundles
to_be_serialized = self.alter_list_data_to_serialize(request, to_be_serialized)
response = self.create_response(request, to_be_serialized)
return response.content
def get_list(self, request, **kwargs):
"""
Overriden mostly to modify how the response is generated.
Returns a serialized list of resources.
Calls ``obj_get_list`` to provide the data, then handles that result
set and serializes it.
Should return a HttpResponse (200 OK).
"""
#****** Start Copy/Paste from Tastypie*********
# TODO: Uncached for now. Invalidation that works for everyone may be
# impossible.
base_bundle = self.build_bundle(request=request)
objects = self.obj_get_list(bundle=base_bundle, **self.remove_api_resource_names(kwargs))
sorted_objects = self.apply_sorting(objects, options=request.GET)
paginator = self._meta.paginator_class(request.GET, sorted_objects, resource_uri=self.get_resource_uri(), limit=self._meta.limit, max_limit=self._meta.max_limit, collection_name=self._meta.collection_name)
to_be_serialized = paginator.page()
#****** END Copy/Paste from Tastypie*********
#Get the queryset for the response
final_qs = to_be_serialized[self._meta.collection_name]
#Use cached_with to cache the response content
create_response_content = partial(self.create_response_content, request=request, to_be_serialized=to_be_serialized)
response = self.create_cached_response(
request, cached_with(
final_qs, create_response_content, get_response_key(request), timeout=3600))
return response
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment