mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-10-29 23:17:45 +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