Skip to content

Instantly share code, notes, and snippets.

@olivergeorge
Created July 19, 2015 11:42
Show Gist options
  • Save olivergeorge/5d1ff49023c9b9e05500 to your computer and use it in GitHub Desktop.
Save olivergeorge/5d1ff49023c9b9e05500 to your computer and use it in GitHub Desktop.
Django REST Framework experiment to batch up many GET requests
import json
from urlparse import urlparse
from rest_framework.decorators import api_view
from django.core.urlresolvers import resolve, Resolver404
from rest_framework.request import QueryDict
from wrapt.wrappers import ObjectProxy
from rest_framework.response import Response
from rest_framework import status
class SubRequest(ObjectProxy):
"""
This is an elaborate mechanism to derive a request based on the original
but with new query_params.
NOTE: There might be a better approach. Advice?
"""
def __init__(self, request, query_params):
super(SubRequest, self).__init__(request)
self._query_params = query_params
def __getattr__(self, item):
if item == 'GET':
return self._query_params
return super(SubRequest, self).__getattr__(item)
@api_view(http_method_names=['GET'])
def payload(request):
"""
This is an attempt to build a view which allows multiple GET requests to be included
in the response. Each query is resolved via a urlconf meaning that the views
are defined and normal permissions are used.
HACK: The approach to reusing the request object with different query_params is
a bit shameful. I'd love to know a better approach.
"""
assert 'urls' in request.query_params
urls_param = request.query_params.get('urls', None)
assert isinstance(urls_param, basestring)
query_urls = json.loads(urls_param)
assert isinstance(query_urls, list)
payload = []
for query_url in query_urls:
assert isinstance(query_url, basestring)
url = urlparse(query_url)
try:
view, args, kwargs = resolve(url.path)
except Resolver404:
return Response(status=status.HTTP_400_BAD_REQUEST)
#
# HACK: This is a workaround. Unsure how to create a suitable request
# for use calling view. To clone... to create... to wrap: I chose wrap.
#
# NOTE: Without this you can't use DRF filters.
#
query_params = QueryDict(url.query, mutable=True)
query_request = SubRequest(request, query_params)
response = view(query_request, *args, **kwargs)
payload.append([query_url, response.data])
return Response(data=payload)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment