Ticket #15010: template-response-current_app.2.txt

File template-response-current_app.2.txt, 12.7 KB (added by Chris Adams, 13 years ago)
Line 
1From 18bb674234e836ba3a8aa6b63c9001100a03b7d0 Mon Sep 17 00:00:00 2001
2From: Chris Adams <chris@improbable.org>
3Date: Mon, 3 Jan 2011 11:57:26 -0500
4Subject: [PATCH 1/5] TemplateResponse: accept a current_app parameter for RequestContext
5
6This simplifies cases such as the Django admin conversion in #15008 where the
7need to set current_app requires an extra import and creating the RequestContext
8manually.
9---
10 django/template/response.py | 7 +++++--
11 tests/regressiontests/templates/response.py | 7 +++++++
12 2 files changed, 12 insertions(+), 2 deletions(-)
13
14diff --git a/django/template/response.py b/django/template/response.py
15index d89fee0..629461a 100644
16--- a/django/template/response.py
17+++ b/django/template/response.py
18@@ -90,11 +90,14 @@ class SimpleTemplateResponse(HttpResponse):
19
20 class TemplateResponse(SimpleTemplateResponse):
21 def __init__(self, request, template, context=None, mimetype=None,
22- status=None, content_type=None):
23+ status=None, content_type=None, current_app=None):
24 # self.request gets over-written by django.test.client.Client - and
25 # unlike context_data and template_name the _request should not
26 # be considered part of the public API.
27 self._request = request
28+ # As a convenience we'll allow callers to provide current_app without
29+ # having to avoid needing to create the RequestContext directly
30+ self._current_app = current_app
31 super(TemplateResponse, self).__init__(
32 template, context, mimetype, status, content_type)
33
34@@ -105,4 +108,4 @@ class TemplateResponse(SimpleTemplateResponse):
35 if isinstance(context, Context):
36 return context
37 else:
38- return RequestContext(self._request, context)
39+ return RequestContext(self._request, context, current_app=self._current_app)
40diff --git a/tests/regressiontests/templates/response.py b/tests/regressiontests/templates/response.py
41index 8bdf7f4..2f0d2c7 100644
42--- a/tests/regressiontests/templates/response.py
43+++ b/tests/regressiontests/templates/response.py
44@@ -172,3 +172,10 @@ class TemplateResponseTest(BaseTemplateResponseTest):
45 'application/json', 504)
46 self.assertEqual(response['content-type'], 'application/json')
47 self.assertEqual(response.status_code, 504)
48+
49+ def test_custom_app(self):
50+ response = self._response('{{ foo }}', current_app="foobar")
51+
52+ rc = response.resolve_context(response.context_data)
53+
54+ self.assertEqual(rc.current_app, 'foobar')
55--
561.7.0.2
57
58
59From fc912c9def744d5a504db15a8061610eee899597 Mon Sep 17 00:00:00 2001
60From: Chris Adams <chris@improbable.org>
61Date: Mon, 3 Jan 2011 21:33:30 -0500
62Subject: [PATCH 2/5] Add current_app support to shortcuts.render
63
64This parallels the earlier change to TemplateResponse, providing a convenient way to pass current_app without having to instantiate a RequestContext by hand.
65
66See http://code.djangoproject.com/ticket/15010
67---
68 django/shortcuts/__init__.py | 10 +++++++++-
69 tests/regressiontests/views/tests/shortcuts.py | 4 ++++
70 tests/regressiontests/views/urls.py | 2 +-
71 tests/regressiontests/views/views.py | 6 ++++++
72 4 files changed, 20 insertions(+), 2 deletions(-)
73
74diff --git a/django/shortcuts/__init__.py b/django/shortcuts/__init__.py
75index b7d69b5..6347d3f 100644
76--- a/django/shortcuts/__init__.py
77+++ b/django/shortcuts/__init__.py
78@@ -29,7 +29,15 @@ def render(request, *args, **kwargs):
79 'content_type': kwargs.pop('content_type', None),
80 'status': kwargs.pop('status', None),
81 }
82- kwargs['context_instance'] = kwargs.get('context_instance', RequestContext(request))
83+
84+ if 'context_instance' in kwargs:
85+ context_instance = kwargs.pop("context_instance")
86+ else:
87+ current_app = kwargs.pop("current_app", None)
88+ context_instance = RequestContext(request, current_app=current_app)
89+
90+ kwargs['context_instance'] = context_instance
91+
92 return HttpResponse(loader.render_to_string(*args, **kwargs),
93 **httpresponse_kwargs)
94
95diff --git a/tests/regressiontests/views/tests/shortcuts.py b/tests/regressiontests/views/tests/shortcuts.py
96index 3f260fe..fa8408c 100644
97--- a/tests/regressiontests/views/tests/shortcuts.py
98+++ b/tests/regressiontests/views/tests/shortcuts.py
99@@ -56,3 +56,7 @@ class ShortcutTests(TestCase):
100 self.assertEquals(response.status_code, 403)
101 self.assertEquals(response.content, 'FOO.BAR../path/to/static/media\n')
102
103+ def test_render_with_current_app(self):
104+ response = self.client.get('/views/shortcuts/render/current_app/')
105+ self.assertEquals(response.context.current_app, "foobar_app")
106+
107diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py
108index 7cba5f6..7dad098 100644
109--- a/tests/regressiontests/views/urls.py
110+++ b/tests/regressiontests/views/urls.py
111@@ -151,7 +151,7 @@ urlpatterns += patterns('regressiontests.views.views',
112 (r'^shortcuts/render/base_context/$', 'render_view_with_base_context'),
113 (r'^shortcuts/render/content_type/$', 'render_view_with_content_type'),
114 (r'^shortcuts/render/status/$', 'render_view_with_status'),
115-
116+ (r'^shortcuts/render/current_app/$', 'render_view_with_current_app'),
117 )
118
119 # simple generic views.
120diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
121index ec017bd..9c9b4c5 100644
122--- a/tests/regressiontests/views/views.py
123+++ b/tests/regressiontests/views/views.py
124@@ -101,3 +101,9 @@ def render_view_with_status(request):
125 'foo': 'FOO',
126 'bar': 'BAR',
127 }, status=403)
128+
129+def render_view_with_current_app(request):
130+ return render(request, 'debug/render_test.html', {
131+ 'foo': 'FOO',
132+ 'bar': 'BAR',
133+ }, current_app="foobar_app")
134--
1351.7.0.2
136
137
138From d1024ace8965230d5eac7d2a7a8cefeeefc3b36d Mon Sep 17 00:00:00 2001
139From: Chris Adams <chris@improbable.org>
140Date: Mon, 3 Jan 2011 21:46:51 -0500
141Subject: [PATCH 3/5] Documentation for current_app on render shortcut and TemplateResponse
142
143Basic documentation and a pointer to the namespaced URL resolution strategy.
144---
145 docs/ref/template-response.txt | 7 ++++++-
146 docs/topics/http/shortcuts.txt | 9 +++++++--
147 2 files changed, 13 insertions(+), 3 deletions(-)
148
149diff --git a/docs/ref/template-response.txt b/docs/ref/template-response.txt
150index 3b136b6..d4fe2c4 100644
151--- a/docs/ref/template-response.txt
152+++ b/docs/ref/template-response.txt
153@@ -129,7 +129,7 @@ TemplateResponse objects
154 Methods
155 -------
156
157-.. method:: TemplateResponse.__init__(request, template, context=None, mimetype=None, status=None, content_type=None)
158+.. method:: TemplateResponse.__init__(request, template, context=None, mimetype=None, status=None, content_type=None, current_app=None)
159
160 Instantiates an ``TemplateResponse`` object with the given
161 template, context, MIME type and HTTP status.
162@@ -158,6 +158,11 @@ Methods
163 ``content_type`` is used. If neither is given,
164 :setting:`DEFAULT_CONTENT_TYPE` is used.
165
166+ ``current_app``
167+ A hint indicating which application contains the current view. See the
168+ :ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>`
169+ for more information.
170+
171
172 The rendering process
173 =====================
174diff --git a/docs/topics/http/shortcuts.txt b/docs/topics/http/shortcuts.txt
175index 1c1dc9e..9d72521 100644
176--- a/docs/topics/http/shortcuts.txt
177+++ b/docs/topics/http/shortcuts.txt
178@@ -15,7 +15,7 @@ introduce controlled coupling for convenience's sake.
179 ``render``
180 ==========
181
182-.. function:: render(request, template[, dictionary][, context_instance][, content_type][, status])
183+.. function:: render(request, template[, dictionary][, context_instance][, content_type][, status][, current_app])
184
185 .. versionadded:: 1.3
186
187@@ -23,7 +23,7 @@ introduce controlled coupling for convenience's sake.
188 :class:`~django.http.HttpResponse` object with that rendered text.
189
190 :func:`render()` is the same as a call to
191- :func:`render_to_response()` with a context_instance argument that
192+ :func:`render_to_response()` with a `context_instance` argument that
193 that forces the use of a :class:`RequestContext`.
194
195 Required arguments
196@@ -55,6 +55,11 @@ Optional arguments
197 ``status``
198 The status code for the response. Defaults to ``200``.
199
200+``current_app``
201+ A hint indicating which application contains the current view. See the
202+ :ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>`
203+ for more information.
204+
205 Example
206 -------
207
208--
2091.7.0.2
210
211
212From 3525c20f5c7375c3ab13b5a509b0be6c588a0254 Mon Sep 17 00:00:00 2001
213From: Chris Adams <chris@improbable.org>
214Date: Mon, 3 Jan 2011 22:05:13 -0500
215Subject: [PATCH 4/5] render(): Added a simple current_app sanity check
216
217This enforces a simple policy: render() will only set current_app on
218RequestContexts which it creates.
219---
220 django/shortcuts/__init__.py | 2 ++
221 tests/regressiontests/views/tests/shortcuts.py | 3 +++
222 tests/regressiontests/views/urls.py | 1 +
223 tests/regressiontests/views/views.py | 8 ++++++++
224 4 files changed, 14 insertions(+), 0 deletions(-)
225
226diff --git a/django/shortcuts/__init__.py b/django/shortcuts/__init__.py
227index 6347d3f..98116f0 100644
228--- a/django/shortcuts/__init__.py
229+++ b/django/shortcuts/__init__.py
230@@ -32,6 +32,8 @@ def render(request, *args, **kwargs):
231
232 if 'context_instance' in kwargs:
233 context_instance = kwargs.pop("context_instance")
234+ if kwargs.get("current_app", None):
235+ raise ValueError("If you provide a context_instance you must set its current_app before calling render()")
236 else:
237 current_app = kwargs.pop("current_app", None)
238 context_instance = RequestContext(request, current_app=current_app)
239diff --git a/tests/regressiontests/views/tests/shortcuts.py b/tests/regressiontests/views/tests/shortcuts.py
240index fa8408c..c974348 100644
241--- a/tests/regressiontests/views/tests/shortcuts.py
242+++ b/tests/regressiontests/views/tests/shortcuts.py
243@@ -60,3 +60,6 @@ class ShortcutTests(TestCase):
244 response = self.client.get('/views/shortcuts/render/current_app/')
245 self.assertEquals(response.context.current_app, "foobar_app")
246
247+ def test_render_with_current_app_conflict(self):
248+ self.assertRaises(ValueError, self.client.get, '/views/shortcuts/render/current_app_conflict/')
249+
250diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py
251index 7dad098..a170efb 100644
252--- a/tests/regressiontests/views/urls.py
253+++ b/tests/regressiontests/views/urls.py
254@@ -152,6 +152,7 @@ urlpatterns += patterns('regressiontests.views.views',
255 (r'^shortcuts/render/content_type/$', 'render_view_with_content_type'),
256 (r'^shortcuts/render/status/$', 'render_view_with_status'),
257 (r'^shortcuts/render/current_app/$', 'render_view_with_current_app'),
258+ (r'^shortcuts/render/current_app_conflict/$', 'render_view_with_current_app_conflict'),
259 )
260
261 # simple generic views.
262diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
263index 9c9b4c5..e4e7c3d 100644
264--- a/tests/regressiontests/views/views.py
265+++ b/tests/regressiontests/views/views.py
266@@ -107,3 +107,11 @@ def render_view_with_current_app(request):
267 'foo': 'FOO',
268 'bar': 'BAR',
269 }, current_app="foobar_app")
270+
271+def render_view_with_current_app_conflict(request):
272+ # This should fail because we don't passing both a current_app and
273+ # context_instance:
274+ return render(request, 'debug/render_test.html', {
275+ 'foo': 'FOO',
276+ 'bar': 'BAR',
277+ }, current_app="foobar_app", context_instance=RequestContext(request))
278--
2791.7.0.2
280
281
282From 67b08c22bffeb7ab4014fa22b99a67f3c684240e Mon Sep 17 00:00:00 2001
283From: Chris Adams <chris@improbable.org>
284Date: Mon, 3 Jan 2011 22:13:48 -0500
285Subject: [PATCH 5/5] shortcuts.render(): test update
286
287* Add positive assertion that current_app is not accidentally set
288---
289 tests/regressiontests/views/tests/shortcuts.py | 1 +
290 1 files changed, 1 insertions(+), 0 deletions(-)
291
292diff --git a/tests/regressiontests/views/tests/shortcuts.py b/tests/regressiontests/views/tests/shortcuts.py
293index c974348..c5f664e 100644
294--- a/tests/regressiontests/views/tests/shortcuts.py
295+++ b/tests/regressiontests/views/tests/shortcuts.py
296@@ -38,6 +38,7 @@ class ShortcutTests(TestCase):
297 self.assertEquals(response.status_code, 200)
298 self.assertEquals(response.content, 'FOO.BAR../path/to/static/media\n')
299 self.assertEquals(response['Content-Type'], 'text/html; charset=utf-8')
300+ self.assertEquals(response.context.current_app, None)
301
302 def test_render_with_base_context(self):
303 response = self.client.get('/views/shortcuts/render/base_context/')
304--
3051.7.0.2
306
Back to Top