mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-26 19:43:59 +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: Status code text for RFC 6585 status codes
|
||||
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:
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||
# although not all choices may be available on all operating systems.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import pickle
|
||||
import re
|
||||
|
||||
from django.conf.urls.defaults import patterns, url, include
|
||||
from django.core.cache import cache
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
|
@ -83,6 +85,7 @@ class HTMLView1(APIView):
|
|||
urlpatterns = patterns('',
|
||||
url(r'^.*\.(?P<format>.+)$', 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/nojsonrenderer$', MockGETView.as_view(renderer_classes=[JSONPRenderer])),
|
||||
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.endswith('</root>'))
|
||||
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