Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add option to redirect_to view to allow passing along the query string

from the original request. Default is current behaviour, which is not to
pass the query string (it often won't be appropriate to do so).

Thanks to steingrd@ifi.uio.no for the patch and tests. Fixed #9966.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@13746 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit fffe0a00a383f46fdfb8de44d56f8ae2e2ee09de 1 parent 04f50c1
Malcolm Tredinnick authored September 11, 2010
10  django/views/generic/simple.py
@@ -17,7 +17,7 @@ def direct_to_template(request, template, extra_context=None, mimetype=None, **k
17 17
     t = loader.get_template(template)
18 18
     return HttpResponse(t.render(c), mimetype=mimetype)
19 19
 
20  
-def redirect_to(request, url, permanent=True, **kwargs):
  20
+def redirect_to(request, url, permanent=True, query_string=False, **kwargs):
21 21
     """
22 22
     Redirect to a given URL.
23 23
 
@@ -33,7 +33,15 @@ def redirect_to(request, url, permanent=True, **kwargs):
33 33
 
34 34
     If the ``permanent`` argument is False, then the response will have a 302
35 35
     HTTP status code. Otherwise, the status code will be 301.
  36
+
  37
+    If the ``query_string`` argument is True, then the GET query string
  38
+    from the request is appended to the URL.
  39
+
36 40
     """
  41
+    args = request.META["QUERY_STRING"]
  42
+    if args and query_string and url is not None:
  43
+        url = "%s?%s" % (url, args)
  44
+
37 45
     if url is not None:
38 46
         klass = permanent and HttpResponsePermanentRedirect or HttpResponseRedirect
39 47
         return klass(url % kwargs)
6  docs/ref/generic-views.txt
@@ -88,9 +88,15 @@ If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410).
88 88
       redirect will use status code 301. If ``False``, then the redirect will
89 89
       use status code 302. By default, ``permanent`` is ``True``.
90 90
 
  91
+    * ``query_string``: Whether to pass along the GET query string to
  92
+      the new location. If ``True``, then the query string is appended
  93
+      to the URL. If ``False``, then the query string is discarded. By
  94
+      default, ``query_string`` is ``False``.
  95
+
91 96
 .. versionadded:: 1.1
92 97
     The ``permanent`` keyword argument is new in Django 1.1.
93 98
 
  99
+
94 100
 **Example:**
95 101
 
96 102
 This example issues a permanent redirect (HTTP status code 301) from
1  tests/regressiontests/views/tests/__init__.py
@@ -2,6 +2,7 @@
2 2
 from defaults import *
3 3
 from generic.create_update import *
4 4
 from generic.date_based import *
  5
+from generic.simple import *
5 6
 from i18n import *
6 7
 from specials import *
7 8
 from static import *
38  tests/regressiontests/views/tests/generic/simple.py
... ...
@@ -0,0 +1,38 @@
  1
+# coding: utf-8
  2
+
  3
+from django.test import TestCase
  4
+
  5
+class RedirectToTest(TestCase):
  6
+    def test_redirect_to_returns_permanent_redirect(self):
  7
+        "simple.redirect_to returns a permanent redirect (301) by default"
  8
+        response = self.client.get('/views/simple/redirect_to/')
  9
+        self.assertEqual(response.status_code, 301)
  10
+        self.assertEqual('http://testserver/views/simple/target/', response['Location'])
  11
+
  12
+    def test_redirect_to_can_return_a_temporary_redirect(self):
  13
+        "simple.redirect_to returns a temporary redirect (302) when explicitely asked to"
  14
+        response = self.client.get('/views/simple/redirect_to_temp/')
  15
+        self.assertEqual(response.status_code, 302)
  16
+        self.assertEqual('http://testserver/views/simple/target/', response['Location'])
  17
+
  18
+    def test_redirect_to_on_empty_url_returns_gone(self):
  19
+        "simple.redirect_to returns resource gone (410) when given a None url"
  20
+        response = self.client.get('/views/simple/redirect_to_none/')
  21
+        self.assertEqual(response.status_code, 410)
  22
+
  23
+    def test_redirect_to_allows_formatted_url_string(self):
  24
+        "simple.redirect_to uses string interpolation on target url for keyword args"
  25
+        response = self.client.get('/views/simple/redirect_to_arg/42/')
  26
+        self.assertEqual(response.status_code, 301)
  27
+        self.assertEqual('http://testserver/views/simple/target_arg/42/', response['Location'])
  28
+
  29
+    def test_redirect_to_allows_query_string_to_be_passed(self):
  30
+        "simple.redirect_to configured with query_string=True passes on any query string"
  31
+        # the default is to not forward the query string
  32
+        response = self.client.get('/views/simple/redirect_to/?param1=foo&param2=bar')
  33
+        self.assertEqual(response.status_code, 301)
  34
+        self.assertEqual('http://testserver/views/simple/target/', response['Location'])
  35
+        # views configured with query_string=True however passes the query string along
  36
+        response = self.client.get('/views/simple/redirect_to_query/?param1=foo&param2=bar')
  37
+        self.assertEqual(response.status_code, 301)
  38
+        self.assertEqual('http://testserver/views/simple/target/?param1=foo&param2=bar', response['Location'])
10  tests/regressiontests/views/urls.py
@@ -77,7 +77,6 @@
77 77
 )
78 78
 
79 79
 # crud generic views.
80  
-
81 80
 urlpatterns += patterns('django.views.generic.create_update',
82 81
     (r'^create_update/member/create/article/$', 'create_object',
83 82
         dict(login_required=True, model=Article)),
@@ -123,3 +122,12 @@
123 122
     url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
124 123
     url(r'template_exception/(?P<n>\d+)/$', 'template_exception', name='template_exception'),
125 124
 )
  125
+
  126
+# simple generic views.
  127
+urlpatterns += patterns('django.views.generic.simple',
  128
+    (r'^simple/redirect_to/$', 'redirect_to', dict(url='/views/simple/target/')),
  129
+    (r'^simple/redirect_to_temp/$', 'redirect_to', dict(url='/views/simple/target/', permanent=False)),
  130
+    (r'^simple/redirect_to_none/$', 'redirect_to', dict(url=None)),
  131
+    (r'^simple/redirect_to_arg/(?P<id>\d+)/$', 'redirect_to', dict(url='/views/simple/target_arg/%(id)s/')),
  132
+    (r'^simple/redirect_to_query/$', 'redirect_to', dict(url='/views/simple/target/', query_string=True)),
  133
+)

0 notes on commit fffe0a0

Please sign in to comment.
Something went wrong with that request. Please try again.