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/django/template/response.py
+++ b/django/template/response.py
@@ -90,11 +90,14 @@ class SimpleTemplateResponse(HttpResponse):
 
 class TemplateResponse(SimpleTemplateResponse):
     def __init__(self, request, template, context=None, mimetype=None,
-            status=None, content_type=None):
+            status=None, content_type=None, current_app=None):
         # self.request gets over-written by django.test.client.Client - and
         # unlike context_data and template_name the _request should not
         # be considered part of the public API.
         self._request = request
+        # As a convenience we'll allow callers to provide current_app without
+        # having to avoid needing to create the RequestContext directly
+        self._current_app = current_app
         super(TemplateResponse, self).__init__(
             template, context, mimetype, status, content_type)
 
@@ -105,4 +108,4 @@ class TemplateResponse(SimpleTemplateResponse):
         if isinstance(context, Context):
             return context
         else:
-            return RequestContext(self._request, context)
+            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/tests/regressiontests/templates/response.py
+++ b/tests/regressiontests/templates/response.py
@@ -172,3 +172,10 @@ class TemplateResponseTest(BaseTemplateResponseTest):
                                     'application/json', 504)
         self.assertEqual(response['content-type'], 'application/json')
         self.assertEqual(response.status_code, 504)
+
+    def test_custom_app(self):
+        response = self._response('{{ foo }}', current_app="foobar")
+
+        rc = response.resolve_context(response.context_data)
+
+        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/django/shortcuts/__init__.py
+++ b/django/shortcuts/__init__.py
@@ -29,7 +29,15 @@ def render(request, *args, **kwargs):
         'content_type': kwargs.pop('content_type', None),
         'status': kwargs.pop('status', None),
     }
-    kwargs['context_instance'] = kwargs.get('context_instance', RequestContext(request))
+
+    if 'context_instance' in kwargs:
+        context_instance = kwargs.pop("context_instance")
+    else:
+        current_app = kwargs.pop("current_app", None)
+        context_instance = RequestContext(request, current_app=current_app)
+
+    kwargs['context_instance'] = context_instance
+
     return HttpResponse(loader.render_to_string(*args, **kwargs),
                         **httpresponse_kwargs)
 
diff --git a/tests/regressiontests/views/tests/shortcuts.py b/tests/regressiontests/views/tests/shortcuts.py
index 3f260fe..fa8408c 100644
--- a/tests/regressiontests/views/tests/shortcuts.py
+++ b/tests/regressiontests/views/tests/shortcuts.py
@@ -56,3 +56,7 @@ class ShortcutTests(TestCase):
         self.assertEquals(response.status_code, 403)
         self.assertEquals(response.content, 'FOO.BAR../path/to/static/media\n')
 
+    def test_render_with_current_app(self):
+        response = self.client.get('/views/shortcuts/render/current_app/')
+        self.assertEquals(response.context.current_app, "foobar_app")
+
diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py
index 7cba5f6..7dad098 100644
--- a/tests/regressiontests/views/urls.py
+++ b/tests/regressiontests/views/urls.py
@@ -151,7 +151,7 @@ urlpatterns += patterns('regressiontests.views.views',
     (r'^shortcuts/render/base_context/$', 'render_view_with_base_context'),
     (r'^shortcuts/render/content_type/$', 'render_view_with_content_type'),
     (r'^shortcuts/render/status/$', 'render_view_with_status'),
-
+    (r'^shortcuts/render/current_app/$', 'render_view_with_current_app'),
 )
 
 # simple generic views.
diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
index ec017bd..9c9b4c5 100644
--- a/tests/regressiontests/views/views.py
+++ b/tests/regressiontests/views/views.py
@@ -101,3 +101,9 @@ def render_view_with_status(request):
         'foo': 'FOO',
         'bar': 'BAR',
     }, status=403)
+
+def render_view_with_current_app(request):
+    return render(request, 'debug/render_test.html', {
+        'foo': 'FOO',
+        'bar': 'BAR',
+    }, 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/docs/ref/template-response.txt
+++ b/docs/ref/template-response.txt
@@ -129,7 +129,7 @@ TemplateResponse objects
 Methods
 -------
 
-.. method:: TemplateResponse.__init__(request, template, context=None, mimetype=None, status=None, content_type=None)
+.. method:: TemplateResponse.__init__(request, template, context=None, mimetype=None, status=None, content_type=None, current_app=None)
 
     Instantiates an ``TemplateResponse`` object with the given
     template, context, MIME type and HTTP status.
@@ -158,6 +158,11 @@ Methods
         ``content_type`` is used. If neither is given,
         :setting:`DEFAULT_CONTENT_TYPE` is used.
 
+    ``current_app``
+        A hint indicating which application contains the current view. See the
+        :ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>`
+        for more information.
+
 
 The rendering process
 =====================
diff --git a/docs/topics/http/shortcuts.txt b/docs/topics/http/shortcuts.txt
index 1c1dc9e..9d72521 100644
--- a/docs/topics/http/shortcuts.txt
+++ b/docs/topics/http/shortcuts.txt
@@ -15,7 +15,7 @@ introduce controlled coupling for convenience's sake.
 ``render``
 ==========
 
-.. function:: render(request, template[, dictionary][, context_instance][, content_type][, status])
+.. function:: render(request, template[, dictionary][, context_instance][, content_type][, status][, current_app])
 
    .. versionadded:: 1.3
 
@@ -23,7 +23,7 @@ introduce controlled coupling for convenience's sake.
    :class:`~django.http.HttpResponse` object with that rendered text.
 
    :func:`render()` is the same as a call to
-   :func:`render_to_response()` with a context_instance argument that
+   :func:`render_to_response()` with a `context_instance` argument that
    that forces the use of a :class:`RequestContext`.
 
 Required arguments
@@ -55,6 +55,11 @@ Optional arguments
 ``status``
     The status code for the response. Defaults to ``200``.
 
+``current_app``
+    A hint indicating which application contains the current view. See the
+    :ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>`
+    for more information.
+
 Example
 -------
 
-- 
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/django/shortcuts/__init__.py
+++ b/django/shortcuts/__init__.py
@@ -32,6 +32,8 @@ def render(request, *args, **kwargs):
 
     if 'context_instance' in kwargs:
         context_instance = kwargs.pop("context_instance")
+        if kwargs.get("current_app", None):
+            raise ValueError("If you provide a context_instance you must set its current_app before calling render()")
     else:
         current_app = kwargs.pop("current_app", None)
         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/tests/regressiontests/views/tests/shortcuts.py
+++ b/tests/regressiontests/views/tests/shortcuts.py
@@ -60,3 +60,6 @@ class ShortcutTests(TestCase):
         response = self.client.get('/views/shortcuts/render/current_app/')
         self.assertEquals(response.context.current_app, "foobar_app")
 
+    def test_render_with_current_app_conflict(self):
+        self.assertRaises(ValueError, self.client.get, '/views/shortcuts/render/current_app_conflict/')
+
diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py
index 7dad098..a170efb 100644
--- a/tests/regressiontests/views/urls.py
+++ b/tests/regressiontests/views/urls.py
@@ -152,6 +152,7 @@ urlpatterns += patterns('regressiontests.views.views',
     (r'^shortcuts/render/content_type/$', 'render_view_with_content_type'),
     (r'^shortcuts/render/status/$', 'render_view_with_status'),
     (r'^shortcuts/render/current_app/$', 'render_view_with_current_app'),
+    (r'^shortcuts/render/current_app_conflict/$', 'render_view_with_current_app_conflict'),
 )
 
 # simple generic views.
diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
index 9c9b4c5..e4e7c3d 100644
--- a/tests/regressiontests/views/views.py
+++ b/tests/regressiontests/views/views.py
@@ -107,3 +107,11 @@ def render_view_with_current_app(request):
         'foo': 'FOO',
         'bar': 'BAR',
     }, current_app="foobar_app")
+
+def render_view_with_current_app_conflict(request):
+    # This should fail because we don't passing both a current_app and
+    # context_instance:
+    return render(request, 'debug/render_test.html', {
+        'foo': 'FOO',
+        'bar': 'BAR',
+    }, 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/tests/regressiontests/views/tests/shortcuts.py
+++ b/tests/regressiontests/views/tests/shortcuts.py
@@ -38,6 +38,7 @@ class ShortcutTests(TestCase):
         self.assertEquals(response.status_code, 200)
         self.assertEquals(response.content, 'FOO.BAR../path/to/static/media\n')
         self.assertEquals(response['Content-Type'], 'text/html; charset=utf-8')
+        self.assertEquals(response.context.current_app, None)
 
     def test_render_with_base_context(self):
         response = self.client.get('/views/shortcuts/render/base_context/')
-- 
1.7.0.2

