Ticket #12241: preserve_query_string7.patch
File preserve_query_string7.patch, 11.1 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..06f6cda 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. … … class ModelAdmin(BaseModelAdmin): 714 738 opts = obj._meta 715 739 pk_value = obj._get_pk_val() 716 740 741 # Handle proxy models automatically created by .only() or .defer() 742 verbose_name = opts.verbose_name 743 if obj._deferred: 744 opts_ = opts.proxy_for_model._meta 745 verbose_name = opts_.verbose_name 746 717 747 msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj)} 718 748 # Here, we distinguish between different save types by checking for 719 749 # the presence of keys in request.POST. 750 720 751 if "_continue" in request.POST: 721 752 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: 753 url = self.url_with_querystring(request, 754 post_url_continue % pk_value) 755 elif "_addanother" in request.POST: 756 self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name))) 757 url = self.url_with_querystring(request) 758 elif "_saveasnew" in request.POST: 759 msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(verbose_name), 'obj': obj} 760 self.message_user(request, msg) 761 return HttpResponseRedirect(self.url_with_querystring(request, "../%s/" % pk_value)) 762 elif "_popup" in request.POST: 727 763 return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \ 728 764 # escape() calls force_unicode. 729 765 (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 766 else: 734 767 self.message_user(request, msg) 735 736 768 # Figure out where to redirect. If the user has change permission, 737 769 # redirect to the change-list page for this object. Otherwise, 738 770 # redirect to the admin index. 739 771 if self.has_change_permission(request, None): 740 post_url = '../'772 url = '../' 741 773 else: 742 post_url = '../../../'743 return HttpResponseRedirect(post_url)774 url = '../../../' 775 return HttpResponseRedirect(url) 744 776 745 777 def response_change(self, request, obj): 746 778 """ … … class ModelAdmin(BaseModelAdmin): 759 791 msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_unicode(verbose_name), 'obj': force_unicode(obj)} 760 792 if "_continue" in request.POST: 761 793 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) 794 return HttpResponseRedirect(self.url_with_querystring(request, request.path)) 770 795 elif "_addanother" in request.POST: 771 796 self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(verbose_name))) 772 return HttpResponseRedirect( "../add/")797 return HttpResponseRedirect(self.url_with_querystring(request, "../add/")) 773 798 else: 774 799 self.message_user(request, msg) 775 800 # Figure out where to redirect. If the user has change permission, … … class ModelAdmin(BaseModelAdmin): 780 805 else: 781 806 return HttpResponseRedirect('../../../') 782 807 808 783 809 def response_action(self, request, queryset): 784 810 """ 785 811 Handle an admin action. This is called if a request is POSTed to the -
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'