Skip to content

Commit fffe0a0

Browse files
committed
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 [email protected] for the patch and tests. Fixed #9966. git-svn-id: http://code.djangoproject.com/svn/django/trunk@13746 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 04f50c1 commit fffe0a0

File tree

5 files changed

+63
-2
lines changed

5 files changed

+63
-2
lines changed

django/views/generic/simple.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def direct_to_template(request, template, extra_context=None, mimetype=None, **k
1717
t = loader.get_template(template)
1818
return HttpResponse(t.render(c), mimetype=mimetype)
1919

20-
def redirect_to(request, url, permanent=True, **kwargs):
20+
def redirect_to(request, url, permanent=True, query_string=False, **kwargs):
2121
"""
2222
Redirect to a given URL.
2323
@@ -33,7 +33,15 @@ def redirect_to(request, url, permanent=True, **kwargs):
3333
3434
If the ``permanent`` argument is False, then the response will have a 302
3535
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+
3640
"""
41+
args = request.META["QUERY_STRING"]
42+
if args and query_string and url is not None:
43+
url = "%s?%s" % (url, args)
44+
3745
if url is not None:
3846
klass = permanent and HttpResponsePermanentRedirect or HttpResponseRedirect
3947
return klass(url % kwargs)

docs/ref/generic-views.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,15 @@ If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410).
8888
redirect will use status code 301. If ``False``, then the redirect will
8989
use status code 302. By default, ``permanent`` is ``True``.
9090

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+
9196
.. versionadded:: 1.1
9297
The ``permanent`` keyword argument is new in Django 1.1.
9398

99+
94100
**Example:**
95101

96102
This example issues a permanent redirect (HTTP status code 301) from

tests/regressiontests/views/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from defaults import *
33
from generic.create_update import *
44
from generic.date_based import *
5+
from generic.simple import *
56
from i18n import *
67
from specials import *
78
from static import *
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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'])

tests/regressiontests/views/urls.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
)
7878

7979
# crud generic views.
80-
8180
urlpatterns += patterns('django.views.generic.create_update',
8281
(r'^create_update/member/create/article/$', 'create_object',
8382
dict(login_required=True, model=Article)),
@@ -123,3 +122,12 @@
123122
url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
124123
url(r'template_exception/(?P<n>\d+)/$', 'template_exception', name='template_exception'),
125124
)
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 commit comments

Comments
 (0)