Ticket #12816: render_shortcut.2.diff
File render_shortcut.2.diff, 12.6 KB (added by , 14 years ago) |
---|
-
django/shortcuts/__init__.py
diff -r c67d03486d14 django/shortcuts/__init__.py
a b 5 5 """ 6 6 7 7 from django.template import loader 8 from django.template.response import TemplateResponse 8 9 from django.http import HttpResponse, Http404 9 10 from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect 10 11 from django.db.models.manager import Manager … … 23 24 """ 24 25 Returns an HttpResponseRedirect to the apropriate URL for the arguments 25 26 passed. 26 27 27 28 The arguments could be: 28 29 29 30 * A model: the model's `get_absolute_url()` function will be called. 30 31 31 32 * A view name, possibly with arguments: `urlresolvers.reverse()` will 32 33 be used to reverse-resolve the name. 33 34 34 35 * A URL, which will be used as-is for the redirect location. 35 36 36 37 By default issues a temporary redirect; pass permanent=True to issue a 37 38 permanent redirect 38 39 """ … … 40 41 redirect_class = HttpResponsePermanentRedirect 41 42 else: 42 43 redirect_class = HttpResponseRedirect 43 44 44 45 # If it's a model, use get_absolute_url() 45 46 if hasattr(to, 'get_absolute_url'): 46 47 return redirect_class(to.get_absolute_url()) 47 48 48 49 # Next try a reverse URL resolution. 49 50 try: 50 51 return redirect_class(urlresolvers.reverse(to, args=args, kwargs=kwargs)) … … 55 56 # If this doesn't "feel" like a URL, re-raise. 56 57 if '/' not in to and '.' not in to: 57 58 raise 58 59 59 60 # Finally, fall back and assume it's a URL 60 61 return redirect_class(to) 61 62 … … 101 102 obj_list = list(queryset.filter(*args, **kwargs)) 102 103 if not obj_list: 103 104 raise Http404('No %s matches the given query.' % queryset.model._meta.object_name) 104 return obj_list 105 No newline at end of file 105 return obj_list 106 107 render = TemplateResponse -
new file django/template/response.py
diff -r c67d03486d14 django/template/response.py
- + 1 from django.http import HttpResponse 2 from django.template import loader, Context, RequestContext 3 4 class SimpleTemplateResponse(HttpResponse): 5 6 def __init__(self, template, context=None, mimetype=None, status=None, 7 content_type=None): 8 # These two properties were originally called 'template' and 'context' 9 # but django.test.client.Client was clobbering those leading to really 10 # tricky-to-debug problems 11 self.template_name = template 12 self.template_context = context 13 self.baked = False 14 15 # content argument doesn't make sense here because it will be replaced 16 # with rendered template so we always pass empty string in order to 17 # prevent errors and provide shorter signature. 18 super(SimpleTemplateResponse, self).__init__('', mimetype, status, 19 content_type) 20 21 def resolve_template(self, template): 22 "Accepts a template object, path-to-template or list of paths" 23 if isinstance(template, (list, tuple)): 24 return loader.select_template(template) 25 elif isinstance(template, basestring): 26 return loader.get_template(template) 27 else: 28 return template 29 30 def resolve_context(self, context): 31 "context can be a dictionary or a context object" 32 if isinstance(context, Context): 33 return context 34 else: 35 return Context(context) 36 37 def render(self): 38 template = self.resolve_template(self.template_name) 39 context = self.resolve_context(self.template_context) 40 content = template.render(context) 41 return content 42 43 def bake(self): 44 """ 45 The template is baked the first time you try to access 46 response.content or iterate over it. This is a bit ugly, but is 47 necessary because Django middleware sometimes expects to be able to 48 over-write the content of a response. 49 """ 50 if not self.baked: 51 self.force_bake() 52 53 def force_bake(self): 54 "Call this if you have modified the template or context but are " 55 "unsure if the template has already been baked." 56 self._set_content(self.render()) 57 self.baked = True 58 59 def __iter__(self): 60 self.bake() 61 return super(SimpleTemplateResponse, self).__iter__() 62 63 def _get_content(self): 64 self.bake() 65 return super(SimpleTemplateResponse, self)._get_content() 66 67 def _set_content(self, value): 68 "Overrides rendered content, unless you later call force_bake()" 69 super(SimpleTemplateResponse, self)._set_content(value) 70 71 content = property(_get_content, _set_content) 72 73 class TemplateResponse(SimpleTemplateResponse): 74 75 def __init__(self, request, template, context=None, mimetype=None, 76 status=None, content_type=None): 77 # self.request gets over-written by django.test.client.Client - and 78 # unlike template_context and template_name the _request should not 79 # be considered part of the public API. 80 self._request = request 81 super(TemplateResponse, self).__init__( 82 template, context, mimetype, status, content_type) 83 84 def resolve_context(self, context): 85 if isinstance(context, Context): 86 return context 87 else: 88 return RequestContext(self._request, context) 89 -
new file tests/regressiontests/templates/response.py
diff -r c67d03486d14 tests/regressiontests/templates/response.py
- + 1 from django.utils import unittest 2 from django.test import RequestFactory 3 from django.conf import settings 4 from django.template import Template, Context, RequestContext 5 from django.template.response import TemplateResponse, SimpleTemplateResponse 6 7 # tests rely on fact that django.contrib.auth.context_processors.auth 8 # is in settings.TEMPLATE_CONTEXT_PROCESSORS and global context 9 # processors should only work when RequestContext is used. 10 11 class SimpleTemplateResponseTest(unittest.TestCase): 12 13 def _response(self, template='foo', *args, **kwargs): 14 return SimpleTemplateResponse(Template(template), *args, **kwargs) 15 16 def test_template_resolving(self): 17 18 # templates from 'templates/templates/..' dir can't be loaded so 19 # the base.html template is reused. It is assumed that base.html 20 # contains 'Django Internal Tests' string. 21 22 response = SimpleTemplateResponse('base.html') 23 self.assertIn('Django Internal Tests', response.content) 24 25 response = SimpleTemplateResponse(['foo.html', 'base.html']) 26 self.assertIn('Django Internal Tests', response.content) 27 28 response = self._response() 29 self.assertEqual(response.content, 'foo') 30 31 def test_explicit_baking(self): 32 # explicit baking 33 response = self._response() 34 self.assertFalse(response.baked) 35 response.bake() 36 self.assertTrue(response.baked) 37 38 def test_baking_on_access(self): 39 # the response is baked when content is accessed 40 response = self._response() 41 self.assertFalse(response.baked) 42 content = response.content 43 self.assertTrue(response.baked) 44 self.assertEqual(content, 'foo') 45 46 def test_dict_context(self): 47 response = self._response('{{ foo }}{{ user.is_anonymous }}', 48 {'foo': 'bar'}) 49 self.assertEqual(response.template_context, {'foo': 'bar'}) 50 self.assertEqual(response.content, 'bar') 51 52 def test_context_instance(self): 53 response = self._response('{{ foo }}{{ user.is_anonymous }}', 54 Context({'foo': 'bar'})) 55 self.assertEqual(response.template_context.__class__, Context) 56 self.assertEqual(response.content, 'bar') 57 58 def test_kwargs(self): 59 response = self._response(content_type = 'application/json', status=504) 60 self.assertEqual(response['content-type'], 'application/json') 61 self.assertEqual(response.status_code, 504) 62 63 def test_args(self): 64 response = SimpleTemplateResponse('', {}, 'application/json', 504) 65 self.assertEqual(response['content-type'], 'application/json') 66 self.assertEqual(response.status_code, 504) 67 68 69 class TemplateResponseTest(unittest.TestCase): 70 def setUp(self): 71 self.factory = RequestFactory() 72 73 def _response(self, template='foo', *args, **kwargs): 74 return TemplateResponse(self.factory.get('/'), Template(template), 75 *args, **kwargs) 76 77 def test_render(self): 78 response = self._response('{{ foo }}{{ user.is_anonymous }}') 79 self.assertEqual(response.content, 'True') 80 81 def test_render_with_requestcontext(self): 82 response = self._response('{{ foo }}{{ user.is_anonymous }}', 83 {'foo': 'bar'}) 84 self.assertEqual(response.content, 'barTrue') 85 86 def test_render_with_context(self): 87 response = self._response('{{ foo }}{{ user.is_anonymous }}', 88 Context({'foo': 'bar'})) 89 self.assertEqual(response.content, 'bar') 90 91 def test_kwargs(self): 92 response = self._response(content_type = 'application/json', status=504) 93 self.assertEqual(response['content-type'], 'application/json') 94 self.assertEqual(response.status_code, 504) 95 96 def test_args(self): 97 response = TemplateResponse(self.factory.get('/'), '', {}, 98 'application/json', 504) 99 self.assertEqual(response['content-type'], 'application/json') 100 self.assertEqual(response.status_code, 504) -
tests/regressiontests/templates/tests.py
diff -r c67d03486d14 tests/regressiontests/templates/tests.py
a b 27 27 from unicode import unicode_tests 28 28 from nodelist import NodelistTest 29 29 from smartif import * 30 from response import * 30 31 31 32 try: 32 33 from loaders import * -
new file tests/regressiontests/views/templates/debug/render_test.html
diff -r c67d03486d14 tests/regressiontests/views/templates/debug/render_test.html
- + 1 {{ foo }}.{{ bar }}.{{ baz }}.{{ user.is_anonymous }} -
tests/regressiontests/views/tests/__init__.py
diff -r c67d03486d14 tests/regressiontests/views/tests/__init__.py
a b 7 7 from i18n import * 8 8 from specials import * 9 9 from static import * 10 from shortcuts import * -
new file tests/regressiontests/views/tests/shortcuts.py
diff -r c67d03486d14 tests/regressiontests/views/tests/shortcuts.py
- + 1 from django.utils import unittest 2 from django.test import RequestFactory 3 from django.template import Template 4 from django.shortcuts import render 5 6 def library_view(request): 7 return render(request, 'debug/render_test.html', 8 {'foo': 'foo', 'baz': 'baz'}) 9 10 def customized_context_view(request): 11 response = library_view(request) 12 response.template_context.update({'bar': 'bar', 'baz': 'spam'}) 13 return response 14 15 def customized_template_view(request): 16 response = library_view(request) 17 response.template_name = Template('context does not matter') 18 return response 19 20 21 class RenderTest(unittest.TestCase): 22 23 def setUp(self): 24 self.factory = RequestFactory() 25 self.request = self.factory.get('/') 26 27 def test_library_view(self): 28 response = library_view(self.request) 29 self.assertEqual(response.content, 'foo..baz.True\n') 30 31 def test_customized_context(self): 32 response = customized_context_view(self.request) 33 self.assertEqual(response.content, 'foo.bar.spam.True\n') 34 35 def test_customized_template(self): 36 response = customized_template_view(self.request) 37 self.assertEqual(response.content, 'context does not matter') 38 39 def test_custom_status_and_content_type(self): 40 response = render(self.request, 'base.html', {'foo': 'bar'}, 41 'application/json', 504) 42 self.assertEqual(response.status_code, 504) 43 self.assertEqual(response['content-type'], 'application/json')