From 18bb674234e836ba3a8aa6b63c9001100a03b7d0 Mon Sep 17 00:00:00 2001
From: Chris Adams <chris@improbable.org>
Date: Mon, 3 Jan 2011 11:57:26 -0500
Subject: [PATCH 1/5] TemplateResponse: accept a current_app parameter for RequestContext
This simplifies cases such as the Django admin conversion in #15008 where the
need to set current_app requires an extra import and creating the RequestContext
manually.
---
django/template/response.py | 7 +++++--
tests/regressiontests/templates/response.py | 7 +++++++
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/django/template/response.py b/django/template/response.py
index d89fee0..629461a 100644
a
|
b
|
class SimpleTemplateResponse(HttpResponse):
|
90 | 90 | |
91 | 91 | class TemplateResponse(SimpleTemplateResponse): |
92 | 92 | def __init__(self, request, template, context=None, mimetype=None, |
93 | | status=None, content_type=None): |
| 93 | status=None, content_type=None, current_app=None): |
94 | 94 | # self.request gets over-written by django.test.client.Client - and |
95 | 95 | # unlike context_data and template_name the _request should not |
96 | 96 | # be considered part of the public API. |
97 | 97 | self._request = request |
| 98 | # As a convenience we'll allow callers to provide current_app without |
| 99 | # having to avoid needing to create the RequestContext directly |
| 100 | self._current_app = current_app |
98 | 101 | super(TemplateResponse, self).__init__( |
99 | 102 | template, context, mimetype, status, content_type) |
100 | 103 | |
… |
… |
class TemplateResponse(SimpleTemplateResponse):
|
105 | 108 | if isinstance(context, Context): |
106 | 109 | return context |
107 | 110 | else: |
108 | | return RequestContext(self._request, context) |
| 111 | return RequestContext(self._request, context, current_app=self._current_app) |
diff --git a/tests/regressiontests/templates/response.py b/tests/regressiontests/templates/response.py
index 8bdf7f4..2f0d2c7 100644
a
|
b
|
class TemplateResponseTest(BaseTemplateResponseTest):
|
172 | 172 | 'application/json', 504) |
173 | 173 | self.assertEqual(response['content-type'], 'application/json') |
174 | 174 | self.assertEqual(response.status_code, 504) |
| 175 | |
| 176 | def test_custom_app(self): |
| 177 | response = self._response('{{ foo }}', current_app="foobar") |
| 178 | |
| 179 | rc = response.resolve_context(response.context_data) |
| 180 | |
| 181 | self.assertEqual(rc.current_app, 'foobar') |
--
1.7.0.2
From fc912c9def744d5a504db15a8061610eee899597 Mon Sep 17 00:00:00 2001
From: Chris Adams <chris@improbable.org>
Date: Mon, 3 Jan 2011 21:33:30 -0500
Subject: [PATCH 2/5] Add current_app support to shortcuts.render
This parallels the earlier change to TemplateResponse, providing a convenient way to pass current_app without having to instantiate a RequestContext by hand.
See http://code.djangoproject.com/ticket/15010
---
django/shortcuts/__init__.py | 10 +++++++++-
tests/regressiontests/views/tests/shortcuts.py | 4 ++++
tests/regressiontests/views/urls.py | 2 +-
tests/regressiontests/views/views.py | 6 ++++++
4 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/django/shortcuts/__init__.py b/django/shortcuts/__init__.py
index b7d69b5..6347d3f 100644
a
|
b
|
def render(request, *args, **kwargs):
|
29 | 29 | 'content_type': kwargs.pop('content_type', None), |
30 | 30 | 'status': kwargs.pop('status', None), |
31 | 31 | } |
32 | | kwargs['context_instance'] = kwargs.get('context_instance', RequestContext(request)) |
| 32 | |
| 33 | if 'context_instance' in kwargs: |
| 34 | context_instance = kwargs.pop("context_instance") |
| 35 | else: |
| 36 | current_app = kwargs.pop("current_app", None) |
| 37 | context_instance = RequestContext(request, current_app=current_app) |
| 38 | |
| 39 | kwargs['context_instance'] = context_instance |
| 40 | |
33 | 41 | return HttpResponse(loader.render_to_string(*args, **kwargs), |
34 | 42 | **httpresponse_kwargs) |
35 | 43 | |
diff --git a/tests/regressiontests/views/tests/shortcuts.py b/tests/regressiontests/views/tests/shortcuts.py
index 3f260fe..fa8408c 100644
a
|
b
|
class ShortcutTests(TestCase):
|
56 | 56 | self.assertEquals(response.status_code, 403) |
57 | 57 | self.assertEquals(response.content, 'FOO.BAR../path/to/static/media\n') |
58 | 58 | |
| 59 | def test_render_with_current_app(self): |
| 60 | response = self.client.get('/views/shortcuts/render/current_app/') |
| 61 | self.assertEquals(response.context.current_app, "foobar_app") |
| 62 | |
diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py
index 7cba5f6..7dad098 100644
a
|
b
|
urlpatterns += patterns('regressiontests.views.views',
|
151 | 151 | (r'^shortcuts/render/base_context/$', 'render_view_with_base_context'), |
152 | 152 | (r'^shortcuts/render/content_type/$', 'render_view_with_content_type'), |
153 | 153 | (r'^shortcuts/render/status/$', 'render_view_with_status'), |
154 | | |
| 154 | (r'^shortcuts/render/current_app/$', 'render_view_with_current_app'), |
155 | 155 | ) |
156 | 156 | |
157 | 157 | # simple generic views. |
diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
index ec017bd..9c9b4c5 100644
a
|
b
|
def render_view_with_status(request):
|
101 | 101 | 'foo': 'FOO', |
102 | 102 | 'bar': 'BAR', |
103 | 103 | }, status=403) |
| 104 | |
| 105 | def render_view_with_current_app(request): |
| 106 | return render(request, 'debug/render_test.html', { |
| 107 | 'foo': 'FOO', |
| 108 | 'bar': 'BAR', |
| 109 | }, current_app="foobar_app") |
--
1.7.0.2
From d1024ace8965230d5eac7d2a7a8cefeeefc3b36d Mon Sep 17 00:00:00 2001
From: Chris Adams <chris@improbable.org>
Date: Mon, 3 Jan 2011 21:46:51 -0500
Subject: [PATCH 3/5] Documentation for current_app on render shortcut and TemplateResponse
Basic documentation and a pointer to the namespaced URL resolution strategy.
---
docs/ref/template-response.txt | 7 ++++++-
docs/topics/http/shortcuts.txt | 9 +++++++--
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/docs/ref/template-response.txt b/docs/ref/template-response.txt
index 3b136b6..d4fe2c4 100644
a
|
b
|
TemplateResponse objects
|
129 | 129 | Methods |
130 | 130 | ------- |
131 | 131 | |
132 | | .. method:: TemplateResponse.__init__(request, template, context=None, mimetype=None, status=None, content_type=None) |
| 132 | .. method:: TemplateResponse.__init__(request, template, context=None, mimetype=None, status=None, content_type=None, current_app=None) |
133 | 133 | |
134 | 134 | Instantiates an ``TemplateResponse`` object with the given |
135 | 135 | template, context, MIME type and HTTP status. |
… |
… |
Methods
|
158 | 158 | ``content_type`` is used. If neither is given, |
159 | 159 | :setting:`DEFAULT_CONTENT_TYPE` is used. |
160 | 160 | |
| 161 | ``current_app`` |
| 162 | A hint indicating which application contains the current view. See the |
| 163 | :ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>` |
| 164 | for more information. |
| 165 | |
161 | 166 | |
162 | 167 | The rendering process |
163 | 168 | ===================== |
diff --git a/docs/topics/http/shortcuts.txt b/docs/topics/http/shortcuts.txt
index 1c1dc9e..9d72521 100644
a
|
b
|
introduce controlled coupling for convenience's sake.
|
15 | 15 | ``render`` |
16 | 16 | ========== |
17 | 17 | |
18 | | .. function:: render(request, template[, dictionary][, context_instance][, content_type][, status]) |
| 18 | .. function:: render(request, template[, dictionary][, context_instance][, content_type][, status][, current_app]) |
19 | 19 | |
20 | 20 | .. versionadded:: 1.3 |
21 | 21 | |
… |
… |
introduce controlled coupling for convenience's sake.
|
23 | 23 | :class:`~django.http.HttpResponse` object with that rendered text. |
24 | 24 | |
25 | 25 | :func:`render()` is the same as a call to |
26 | | :func:`render_to_response()` with a context_instance argument that |
| 26 | :func:`render_to_response()` with a `context_instance` argument that |
27 | 27 | that forces the use of a :class:`RequestContext`. |
28 | 28 | |
29 | 29 | Required arguments |
… |
… |
Optional arguments
|
55 | 55 | ``status`` |
56 | 56 | The status code for the response. Defaults to ``200``. |
57 | 57 | |
| 58 | ``current_app`` |
| 59 | A hint indicating which application contains the current view. See the |
| 60 | :ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>` |
| 61 | for more information. |
| 62 | |
58 | 63 | Example |
59 | 64 | ------- |
60 | 65 | |
--
1.7.0.2
From 3525c20f5c7375c3ab13b5a509b0be6c588a0254 Mon Sep 17 00:00:00 2001
From: Chris Adams <chris@improbable.org>
Date: Mon, 3 Jan 2011 22:05:13 -0500
Subject: [PATCH 4/5] render(): Added a simple current_app sanity check
This enforces a simple policy: render() will only set current_app on
RequestContexts which it creates.
---
django/shortcuts/__init__.py | 2 ++
tests/regressiontests/views/tests/shortcuts.py | 3 +++
tests/regressiontests/views/urls.py | 1 +
tests/regressiontests/views/views.py | 8 ++++++++
4 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/django/shortcuts/__init__.py b/django/shortcuts/__init__.py
index 6347d3f..98116f0 100644
a
|
b
|
def render(request, *args, **kwargs):
|
32 | 32 | |
33 | 33 | if 'context_instance' in kwargs: |
34 | 34 | context_instance = kwargs.pop("context_instance") |
| 35 | if kwargs.get("current_app", None): |
| 36 | raise ValueError("If you provide a context_instance you must set its current_app before calling render()") |
35 | 37 | else: |
36 | 38 | current_app = kwargs.pop("current_app", None) |
37 | 39 | context_instance = RequestContext(request, current_app=current_app) |
diff --git a/tests/regressiontests/views/tests/shortcuts.py b/tests/regressiontests/views/tests/shortcuts.py
index fa8408c..c974348 100644
a
|
b
|
class ShortcutTests(TestCase):
|
60 | 60 | response = self.client.get('/views/shortcuts/render/current_app/') |
61 | 61 | self.assertEquals(response.context.current_app, "foobar_app") |
62 | 62 | |
| 63 | def test_render_with_current_app_conflict(self): |
| 64 | self.assertRaises(ValueError, self.client.get, '/views/shortcuts/render/current_app_conflict/') |
| 65 | |
diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py
index 7dad098..a170efb 100644
a
|
b
|
urlpatterns += patterns('regressiontests.views.views',
|
152 | 152 | (r'^shortcuts/render/content_type/$', 'render_view_with_content_type'), |
153 | 153 | (r'^shortcuts/render/status/$', 'render_view_with_status'), |
154 | 154 | (r'^shortcuts/render/current_app/$', 'render_view_with_current_app'), |
| 155 | (r'^shortcuts/render/current_app_conflict/$', 'render_view_with_current_app_conflict'), |
155 | 156 | ) |
156 | 157 | |
157 | 158 | # simple generic views. |
diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
index 9c9b4c5..e4e7c3d 100644
a
|
b
|
def render_view_with_current_app(request):
|
107 | 107 | 'foo': 'FOO', |
108 | 108 | 'bar': 'BAR', |
109 | 109 | }, current_app="foobar_app") |
| 110 | |
| 111 | def render_view_with_current_app_conflict(request): |
| 112 | # This should fail because we don't passing both a current_app and |
| 113 | # context_instance: |
| 114 | return render(request, 'debug/render_test.html', { |
| 115 | 'foo': 'FOO', |
| 116 | 'bar': 'BAR', |
| 117 | }, current_app="foobar_app", context_instance=RequestContext(request)) |
--
1.7.0.2
From 67b08c22bffeb7ab4014fa22b99a67f3c684240e Mon Sep 17 00:00:00 2001
From: Chris Adams <chris@improbable.org>
Date: Mon, 3 Jan 2011 22:13:48 -0500
Subject: [PATCH 5/5] shortcuts.render(): test update
* Add positive assertion that current_app is not accidentally set
---
tests/regressiontests/views/tests/shortcuts.py | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/tests/regressiontests/views/tests/shortcuts.py b/tests/regressiontests/views/tests/shortcuts.py
index c974348..c5f664e 100644
a
|
b
|
class ShortcutTests(TestCase):
|
38 | 38 | self.assertEquals(response.status_code, 200) |
39 | 39 | self.assertEquals(response.content, 'FOO.BAR../path/to/static/media\n') |
40 | 40 | self.assertEquals(response['Content-Type'], 'text/html; charset=utf-8') |
| 41 | self.assertEquals(response.context.current_app, None) |
41 | 42 | |
42 | 43 | def test_render_with_base_context(self): |
43 | 44 | response = self.client.get('/views/shortcuts/render/base_context/') |