mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-30 05:24:00 +03:00
Merge pull request #366 from jmagnusson/master
Support for Djangos caching framework, fixes #346
This commit is contained in:
commit
584c111aab
|
@ -45,3 +45,13 @@ class Response(SimpleTemplateResponse):
|
||||||
# TODO: Deprecate and use a template tag instead
|
# TODO: Deprecate and use a template tag instead
|
||||||
# TODO: Status code text for RFC 6585 status codes
|
# TODO: Status code text for RFC 6585 status codes
|
||||||
return STATUS_CODE_TEXT.get(self.status_code, '')
|
return STATUS_CODE_TEXT.get(self.status_code, '')
|
||||||
|
|
||||||
|
def __getstate__(self):
|
||||||
|
"""
|
||||||
|
Remove attributes from the response that shouldn't be cached
|
||||||
|
"""
|
||||||
|
state = super(Response, self).__getstate__()
|
||||||
|
for key in ('accepted_renderer', 'renderer_context', 'data'):
|
||||||
|
if key in state:
|
||||||
|
del state[key]
|
||||||
|
return state
|
||||||
|
|
|
@ -21,6 +21,12 @@ DATABASES = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CACHES = {
|
||||||
|
'default': {
|
||||||
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Local time zone for this installation. Choices can be found here:
|
# Local time zone for this installation. Choices can be found here:
|
||||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||||
# although not all choices may be available on all operating systems.
|
# although not all choices may be available on all operating systems.
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
import pickle
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from django.conf.urls.defaults import patterns, url, include
|
from django.conf.urls.defaults import patterns, url, include
|
||||||
|
from django.core.cache import cache
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
|
|
||||||
|
@ -83,6 +85,7 @@ class HTMLView1(APIView):
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
|
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
|
||||||
url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
|
url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
|
||||||
|
url(r'^cache$', MockGETView.as_view()),
|
||||||
url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderer_classes=[JSONRenderer, JSONPRenderer])),
|
url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderer_classes=[JSONRenderer, JSONPRenderer])),
|
||||||
url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderer_classes=[JSONPRenderer])),
|
url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderer_classes=[JSONPRenderer])),
|
||||||
url(r'^html$', HTMLView.as_view()),
|
url(r'^html$', HTMLView.as_view()),
|
||||||
|
@ -416,3 +419,89 @@ class XMLRendererTestCase(TestCase):
|
||||||
self.assertTrue(xml.startswith('<?xml version="1.0" encoding="utf-8"?>\n<root>'))
|
self.assertTrue(xml.startswith('<?xml version="1.0" encoding="utf-8"?>\n<root>'))
|
||||||
self.assertTrue(xml.endswith('</root>'))
|
self.assertTrue(xml.endswith('</root>'))
|
||||||
self.assertTrue(string in xml, '%r not in %r' % (string, xml))
|
self.assertTrue(string in xml, '%r not in %r' % (string, xml))
|
||||||
|
|
||||||
|
|
||||||
|
# Tests for caching issue, #346
|
||||||
|
class CacheRenderTest(TestCase):
|
||||||
|
"""
|
||||||
|
Tests specific to caching responses
|
||||||
|
"""
|
||||||
|
|
||||||
|
urls = 'rest_framework.tests.renderers'
|
||||||
|
|
||||||
|
cache_key = 'just_a_cache_key'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_pickling_errors(cls, obj, seen=None):
|
||||||
|
""" Return any errors that would be raised if `obj' is pickled
|
||||||
|
Courtesy of koffie @ http://stackoverflow.com/a/7218986/109897
|
||||||
|
"""
|
||||||
|
if seen == None:
|
||||||
|
seen = []
|
||||||
|
try:
|
||||||
|
state = obj.__getstate__()
|
||||||
|
except AttributeError:
|
||||||
|
return
|
||||||
|
if state == None:
|
||||||
|
return
|
||||||
|
if isinstance(state,tuple):
|
||||||
|
if not isinstance(state[0],dict):
|
||||||
|
state=state[1]
|
||||||
|
else:
|
||||||
|
state=state[0].update(state[1])
|
||||||
|
result = {}
|
||||||
|
for i in state:
|
||||||
|
try:
|
||||||
|
pickle.dumps(state[i],protocol=2)
|
||||||
|
except pickle.PicklingError:
|
||||||
|
if not state[i] in seen:
|
||||||
|
seen.append(state[i])
|
||||||
|
result[i] = cls._get_pickling_errors(state[i],seen)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def http_resp(self, http_method, url):
|
||||||
|
"""
|
||||||
|
Simple wrapper for Client http requests
|
||||||
|
Removes the `client' and `request' attributes from as they are
|
||||||
|
added by django.test.client.Client and not part of caching
|
||||||
|
responses outside of tests.
|
||||||
|
"""
|
||||||
|
method = getattr(self.client, http_method)
|
||||||
|
resp = method(url)
|
||||||
|
del resp.client, resp.request
|
||||||
|
return resp
|
||||||
|
|
||||||
|
def test_obj_pickling(self):
|
||||||
|
"""
|
||||||
|
Test that responses are properly pickled
|
||||||
|
"""
|
||||||
|
resp = self.http_resp('get', '/cache')
|
||||||
|
|
||||||
|
# Make sure that no pickling errors occurred
|
||||||
|
self.assertEqual(self._get_pickling_errors(resp), {})
|
||||||
|
|
||||||
|
# Unfortunately LocMem backend doesn't raise PickleErrors but returns
|
||||||
|
# None instead.
|
||||||
|
cache.set(self.cache_key, resp)
|
||||||
|
self.assertTrue(cache.get(self.cache_key) is not None)
|
||||||
|
|
||||||
|
def test_head_caching(self):
|
||||||
|
"""
|
||||||
|
Test caching of HEAD requests
|
||||||
|
"""
|
||||||
|
resp = self.http_resp('head', '/cache')
|
||||||
|
cache.set(self.cache_key, resp)
|
||||||
|
|
||||||
|
cached_resp = cache.get(self.cache_key)
|
||||||
|
self.assertIsInstance(cached_resp, Response)
|
||||||
|
|
||||||
|
def test_get_caching(self):
|
||||||
|
"""
|
||||||
|
Test caching of GET requests
|
||||||
|
"""
|
||||||
|
resp = self.http_resp('get', '/cache')
|
||||||
|
cache.set(self.cache_key, resp)
|
||||||
|
|
||||||
|
cached_resp = cache.get(self.cache_key)
|
||||||
|
self.assertIsInstance(cached_resp, Response)
|
||||||
|
self.assertEqual(cached_resp.content, resp.content)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user