Ticket #12241: preserve_query_string8.patch
File preserve_query_string8.patch, 10.9 KB (added by , 14 years ago) |
---|
-
django/contrib/admin/options.py
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 43c5503..cadaa82 100644
a b from django.db import models, transaction, router 13 13 from django.db.models.related import RelatedObject 14 14 from django.db.models.fields import BLANK_CHOICE_DASH, FieldDoesNotExist 15 15 from django.db.models.sql.constants import LOOKUP_SEP, QUERY_TERMS 16 from django.http import Http404, HttpResponse, HttpResponseRedirect17 16 from django.shortcuts import get_object_or_404, render_to_response 17 from django.http import Http404, HttpResponse, HttpResponseRedirect, QueryDict 18 18 from django.utils.decorators import method_decorator 19 19 from django.utils.datastructures import SortedDict 20 20 from django.utils.functional import update_wrapper … … class ModelAdmin(BaseModelAdmin): 707 707 "admin/change_form.html" 708 708 ], context, context_instance=context_instance) 709 709 710 def url_with_querystring(self, request, url=None): 711 """ 712 Returns a URL with the query string preserved from the current request. 713 """ 714 if url is None: 715 url = request.path 716 querystring = request.GET.copy() 717 718 # If the new URL has an existing query string, set (or override 719 # existing) values with the new ones explicitly provided. 720 if '?' in url: 721 url, new_qs = url.split('?', 1) 722 for key, value in QueryDict(new_qs): 723 querystring.setlist(key, value) 724 725 # Preserve the admin's "_popup" variable which may have originate in 726 # the POST QueryDict. 727 if '_popup' in request.POST or '_popup' in request.REQUEST: 728 querystring['_popup'] = 1 729 730 if querystring: 731 url = '%s?%s' % (url, querystring.urlencode()) 732 return url 733 710 734 def response_add(self, request, obj, post_url_continue='../%s/'): 711 735 """ 712 736 Determines the HttpResponse for the add_view stage. 713 737 """ 714 738 opts = obj._meta 715 739 pk_value = obj._get_pk_val() 740 verbose_name = opts.verbose_name 716 741 717 msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': force_unicode( opts.verbose_name), 'obj': force_unicode(obj)}742 msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': force_unicode(verbose_name), 'obj': force_unicode(obj)} 718 743 # Here, we distinguish between different save types by checking for 719 744 # the presence of keys in request.POST. 720 745 if "_continue" in request.POST: 721 746 self.message_user(request, msg + ' ' + _("You may edit it again below.")) 722 if "_popup" in request.POST: 723 post_url_continue += "?_popup=1" 724 return HttpResponseRedirect(post_url_continue % pk_value) 725 726 if "_popup" in request.POST: 747 url = self.url_with_querystring(request, 748 post_url_continue % pk_value) 749 elif "_addanother" in request.POST: 750 self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(verbose_name))) 751 url = self.url_with_querystring(request) 752 elif "_saveasnew" in request.POST: 753 msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(verbose_name), 'obj': obj} 754 self.message_user(request, msg) 755 return HttpResponseRedirect(self.url_with_querystring(request, "../%s/" % pk_value)) 756 elif "_popup" in request.POST: 727 757 return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \ 728 758 # escape() calls force_unicode. 729 759 (escape(pk_value), escapejs(obj))) 730 elif "_addanother" in request.POST:731 self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))732 return HttpResponseRedirect(request.path)733 760 else: 734 761 self.message_user(request, msg) 735 736 762 # Figure out where to redirect. If the user has change permission, 737 763 # redirect to the change-list page for this object. Otherwise, 738 764 # redirect to the admin index. 739 765 if self.has_change_permission(request, None): 740 post_url = '../'766 url = '../' 741 767 else: 742 post_url = '../../../'743 return HttpResponseRedirect(post_url)768 url = '../../../' 769 return HttpResponseRedirect(url) 744 770 745 771 def response_change(self, request, obj): 746 772 """ … … class ModelAdmin(BaseModelAdmin): 754 780 opts_ = opts.proxy_for_model._meta 755 781 verbose_name = opts_.verbose_name 756 782 757 pk_value = obj._get_pk_val()758 759 783 msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_unicode(verbose_name), 'obj': force_unicode(obj)} 760 784 if "_continue" in request.POST: 761 785 self.message_user(request, msg + ' ' + _("You may edit it again below.")) 762 if "_popup" in request.REQUEST: 763 return HttpResponseRedirect(request.path + "?_popup=1") 764 else: 765 return HttpResponseRedirect(request.path) 766 elif "_saveasnew" in request.POST: 767 msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(verbose_name), 'obj': obj} 768 self.message_user(request, msg) 769 return HttpResponseRedirect("../%s/" % pk_value) 786 return HttpResponseRedirect(self.url_with_querystring(request, request.path)) 770 787 elif "_addanother" in request.POST: 771 788 self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(verbose_name))) 772 return HttpResponseRedirect( "../add/")789 return HttpResponseRedirect(self.url_with_querystring(request, "../add/")) 773 790 else: 774 791 self.message_user(request, msg) 775 792 # Figure out where to redirect. If the user has change permission, -
tests/regressiontests/admin_views/tests.py
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index ff97acd..1651bb1 100644
a b from django.utils.html import escape 28 28 from django.utils.http import urlencode 29 29 from django.utils.translation import activate, deactivate 30 30 from django.utils import unittest 31 from django.http import QueryDict 31 32 32 33 # local test models 33 34 from models import (Article, BarAccount, CustomArticle, EmptyModel, … … class AdminCustomQuerysetTest(TestCase): 2110 2111 # Message should contain non-ugly model name. Instance representation is set by model's __unicode__() 2111 2112 self.assertContains(response, '<li class="info">The cover letter "John Doe II" was changed successfully.</li>') 2112 2113 2114 2115 class AdminPreserveQSTest(TestCase): 2116 """ 2117 Neither adding nor changing a model will preserve the request query string 2118 after a redirection if the standard "save" button is used within the admin. 2119 """ 2120 action = None 2121 preserves_qs = False 2122 fixtures = ['admin-views-users.xml'] 2123 2124 def setUp(self): 2125 self.client.login(username='super', password='secret') 2126 self.data = {'title': "I Could Go Anywhere", 'content': "Versatile"} 2127 article = Article.objects.create(date=datetime.datetime.now(), 2128 **self.data) 2129 self.data.update({'date_0': u"2008-03-18", 'date_1': u"11:54:58"}) 2130 if self.action: 2131 self.data[self.action] = True 2132 self.pk = article.id 2133 2134 def check_redirect(self, response): 2135 self.assertEqual(response.status_code, 302) 2136 location = urlparse.urlparse(response['Location']) 2137 return QueryDict(location.query) 2138 2139 def test_response_add(self): 2140 url = '/test_admin/admin/admin_views/article/add/' 2141 2142 response = self.client.post('%s?test=1' % url, self.data) 2143 parsed_query_string = self.check_redirect(response) 2144 if self.preserves_qs: 2145 self.assertTrue('test' in parsed_query_string) 2146 else: 2147 self.assertFalse('test' in parsed_query_string) 2148 2149 # Test the popup redirection. 2150 self.data['_popup'] = 1 2151 response = self.client.post(url, self.data) 2152 if self.preserves_qs: 2153 parsed_query_string = self.check_redirect(response) 2154 self.assertTrue('_popup' in parsed_query_string) 2155 else: 2156 self.assertContains(response, 2157 '<script type="text/javascript">opener.dismissAddAnotherPopup') 2158 2159 # Test the popup redirection togethre with 2 other GET parameters. 2160 response = self.client.post('%s?test=1&extra=1' % url, self.data) 2161 if self.preserves_qs: 2162 parsed_query_string = self.check_redirect(response) 2163 self.assertTrue('test' in parsed_query_string) 2164 self.assertTrue('extra' in parsed_query_string) 2165 self.assertTrue('_popup' in parsed_query_string) 2166 else: 2167 self.assertContains(response, 2168 '<script type="text/javascript">opener.dismissAddAnotherPopup') 2169 2170 def test_response_change(self): 2171 url = '/test_admin/admin/admin_views/article/%d/' % self.pk 2172 2173 response = self.client.post('%s?test=1' % url, self.data) 2174 parsed_query_string = self.check_redirect(response) 2175 if self.preserves_qs: 2176 self.assertTrue('test' in parsed_query_string) 2177 else: 2178 self.assertFalse('test' in parsed_query_string) 2179 2180 response = self.client.post(url, self.data) 2181 parsed_query_string = self.check_redirect(response) 2182 self.assertFalse('test' in parsed_query_string) 2183 2184 2185 class AdminPreserveQSOnContinueTest(AdminPreserveQSTest): 2186 """ 2187 Adding or changing a model should preserve the request query string after 2188 the redirection if the "save and continue" button is used within the admin 2189 (Ticket #12241). 2190 """ 2191 action = '_continue' 2192 preserves_qs = True 2193 2194 2195 class AdminPreserveQSOnAddAnotherTest(AdminPreserveQSTest): 2196 """ 2197 Adding or changing a model should preserve the request query string after 2198 the redirection if the "add another" button is used within the admin 2199 (Ticket #12241). 2200 """ 2201 action = '_addanother' 2202 preserves_qs = True 2203 2204 2205 class AdminPreserveQSOnSaveAsNewTest(AdminPreserveQSTest): 2206 """ 2207 Adding or changing a model should preserve the request query string after 2208 the redirection if the "save as new" button is used within the admin 2209 (Ticket #12241). 2210 2211 Only the change view has the "save as new" button, but then 2212 the admin use the response_add for the answer. 2213 """ 2214 action = '_saveasnew' 2215 preserves_qs = True 2216 2217 2113 2218 class AdminInlineFileUploadTest(TestCase): 2114 2219 fixtures = ['admin-views-users.xml', 'admin-views-actions.xml'] 2115 2220 urlbit = 'admin'