Ticket #12241: preserve_query_string8.patch

File preserve_query_string8.patch, 10.9 KB (added by batiste, 5 years ago)

Same as last one, but removing adding the proxy thing in add_view

  • 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 
    1313from django.db.models.related import RelatedObject
    1414from django.db.models.fields import BLANK_CHOICE_DASH, FieldDoesNotExist
    1515from django.db.models.sql.constants import LOOKUP_SEP, QUERY_TERMS
    16 from django.http import Http404, HttpResponse, HttpResponseRedirect
    1716from django.shortcuts import get_object_or_404, render_to_response
     17from django.http import Http404, HttpResponse, HttpResponseRedirect, QueryDict
    1818from django.utils.decorators import method_decorator
    1919from django.utils.datastructures import SortedDict
    2020from django.utils.functional import update_wrapper
    class ModelAdmin(BaseModelAdmin): 
    707707            "admin/change_form.html"
    708708        ], context, context_instance=context_instance)
    709709
     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
    710734    def response_add(self, request, obj, post_url_continue='../%s/'):
    711735        """
    712736        Determines the HttpResponse for the add_view stage.
    713737        """
    714738        opts = obj._meta
    715739        pk_value = obj._get_pk_val()
     740        verbose_name = opts.verbose_name
    716741
    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)}
    718743        # Here, we distinguish between different save types by checking for
    719744        # the presence of keys in request.POST.
    720745        if "_continue" in request.POST:
    721746            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:
    727757            return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
    728758                # escape() calls force_unicode.
    729759                (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)
    733760        else:
    734761            self.message_user(request, msg)
    735 
    736762            # Figure out where to redirect. If the user has change permission,
    737763            # redirect to the change-list page for this object. Otherwise,
    738764            # redirect to the admin index.
    739765            if self.has_change_permission(request, None):
    740                 post_url = '../'
     766                url = '../'
    741767            else:
    742                 post_url = '../../../'
    743             return HttpResponseRedirect(post_url)
     768                url = '../../../'
     769        return HttpResponseRedirect(url)
    744770
    745771    def response_change(self, request, obj):
    746772        """
    class ModelAdmin(BaseModelAdmin): 
    754780            opts_ = opts.proxy_for_model._meta
    755781            verbose_name = opts_.verbose_name
    756782
    757         pk_value = obj._get_pk_val()
    758 
    759783        msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_unicode(verbose_name), 'obj': force_unicode(obj)}
    760784        if "_continue" in request.POST:
    761785            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))
    770787        elif "_addanother" in request.POST:
    771788            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/"))
    773790        else:
    774791            self.message_user(request, msg)
    775792            # 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 
    2828from django.utils.http import urlencode
    2929from django.utils.translation import activate, deactivate
    3030from django.utils import unittest
     31from django.http import QueryDict
    3132
    3233# local test models
    3334from models import (Article, BarAccount, CustomArticle, EmptyModel,
    class AdminCustomQuerysetTest(TestCase): 
    21102111        # Message should contain non-ugly model name. Instance representation is set by model's __unicode__()
    21112112        self.assertContains(response, '<li class="info">The cover letter &quot;John Doe II&quot; was changed successfully.</li>')
    21122113
     2114
     2115class 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
     2185class 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
     2195class 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
     2205class 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
    21132218class AdminInlineFileUploadTest(TestCase):
    21142219    fixtures = ['admin-views-users.xml', 'admin-views-actions.xml']
    21152220    urlbit = 'admin'
Back to Top