Index: django/contrib/admin/options.py
===================================================================
--- django/contrib/admin/options.py	(revision 13350)
+++ django/contrib/admin/options.py	(working copy)
@@ -24,6 +24,9 @@
 from django.utils.translation import ungettext, ugettext_lazy
 from django.utils.encoding import force_unicode
 
+import urllib
+import urlparse
+
 HORIZONTAL, VERTICAL = 1, 2
 # returns the <ul> class for a given radio_admin field
 get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '')
@@ -633,6 +636,20 @@
             "admin/change_form.html"
         ], context, context_instance=context_instance)
 
+    def redirect_with_query_string(self, request, url_continue, msg):
+        """
+        Handle a redirect URL and preserve the query string.
+        """
+        self.message_user(request, msg + ' ' + _("You may edit it again below."))
+        string_dict = urlparse.parse_qs(request.META.get('QUERY_STRING'))
+        if request.POST.has_key("_popup"):
+            string_dict['_popup'] = 1
+
+        if string_dict:
+            return url_continue + '?' + urllib.urlencode(string_dict)
+        
+        return url_continue
+
     def response_add(self, request, obj, post_url_continue='../%s/'):
         """
         Determines the HttpResponse for the add_view stage.
@@ -644,12 +661,11 @@
         # Here, we distinguish between different save types by checking for
         # the presence of keys in request.POST.
         if request.POST.has_key("_continue"):
-            self.message_user(request, msg + ' ' + _("You may edit it again below."))
-            if request.POST.has_key("_popup"):
-                post_url_continue += "?_popup=1"
-            return HttpResponseRedirect(post_url_continue % pk_value)
+            url = post_url_continue % pk_value
+            url = self.redirect_with_query_string(request, url, msg)
+            return HttpResponseRedirect(url)
 
-        if request.POST.has_key("_popup"):
+        if request.POST.has_key('_popup'):
             return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
                 # escape() calls force_unicode.
                 (escape(pk_value), escape(obj)))
@@ -677,11 +693,8 @@
 
         msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj)}
         if request.POST.has_key("_continue"):
-            self.message_user(request, msg + ' ' + _("You may edit it again below."))
-            if request.REQUEST.has_key('_popup'):
-                return HttpResponseRedirect(request.path + "?_popup=1")
-            else:
-                return HttpResponseRedirect(request.path)
+            url = self.redirect_with_query_string(request, request.path, msg)
+            return HttpResponseRedirect(url)
         elif request.POST.has_key("_saveasnew"):
             msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(opts.verbose_name), 'obj': obj}
             self.message_user(request, msg)
Index: tests/regressiontests/admin_views/tests.py
===================================================================
--- tests/regressiontests/admin_views/tests.py	(revision 13350)
+++ tests/regressiontests/admin_views/tests.py	(working copy)
@@ -2,6 +2,7 @@
 
 import re
 import datetime
+import urlparse
 from django.conf import settings
 from django.core.files import temp as tempfile
 from django.contrib.auth import admin # Register auth models with the admin.
@@ -1623,6 +1624,75 @@
             else:
                 self.assertEqual(response.status_code, 404)
 
+class AdminResponseChangeTest(TestCase):
+    fixtures = ['admin-views-users.xml']
+
+    def setUp(self):
+        self.client.login(username='super', password='secret')
+        self.data = {'title':"I Could Go Anywhere", 'content':"Versatile", 'date':datetime.datetime.now()}
+        article = Article.objects.create(**self.data)
+        self.pk = article.id
+
+    def check_redirect(self, response):
+        self.assertEqual(response.status_code, 302)
+        location = urlparse.urlparse(response['Location'])
+        return urlparse.parse_qs(location.query)
+
+    def test_response_add(self):
+        """Add test for #12241: ModelAdmin.response_add should preserve the request
+        query string after the redirection if the "save and continue" button
+        is used within the admin."""
+        
+        self.data['_continue'] = True
+        self.data['date_0'] = u"2008-03-18"
+        self.data['date_1'] = u"11:54:58"
+        response = self.client.post('/test_admin/admin/admin_views/article/%d/?test=1' % self.pk, self.data)
+        parsed_query_string = self.check_redirect(response)
+        self.assertTrue('test' in parsed_query_string.keys())
+
+        response = self.client.post('/test_admin/admin/admin_views/article/add/?test=1', self.data)
+        parsed_query_string = self.check_redirect(response)
+        self.assertTrue('test' in parsed_query_string.keys())
+
+        # test the popup redirection
+        self.data['_popup'] = 1
+        response = self.client.post('/test_admin/admin/admin_views/article/add/', self.data)
+        parsed_query_string = self.check_redirect(response)
+        self.assertTrue('_popup' in parsed_query_string.keys())
+
+        # test the popup redirection and another GET parameter
+        response = self.client.post('/test_admin/admin/admin_views/article/add/?test=1', self.data)
+        parsed_query_string = self.check_redirect(response)
+        self.assertTrue('test' in parsed_query_string.keys())
+        self.assertTrue('_popup' in parsed_query_string.keys())
+
+        # without anything
+        del self.data['_popup']
+        response = self.client.post('/test_admin/admin/admin_views/article/add/', self.data)
+        parsed_query_string = self.check_redirect(response)
+        self.assertFalse('test' in parsed_query_string.keys())
+        self.assertFalse('_popup' in parsed_query_string.keys())
+
+    def test_response_change(self):
+        """Change test for issue #12241. ModelAdmin.response_change should
+        preserve the query string."""
+
+        self.data['date_0'] = u"2008-03-18"
+        self.data['date_1'] = u"11:54:58"
+        self.data['_continue'] = True
+
+        response = self.client.post('/test_admin/admin/admin_views/article/%d/?test=1' % self.pk, self.data)
+        parsed_query_string = self.check_redirect(response)
+        self.assertTrue('test' in parsed_query_string.keys())
+        self.assertFalse('_popup' in parsed_query_string.keys())
+        
+        response = self.client.post('/test_admin/admin/admin_views/article/%d/' % self.pk, self.data)
+        parsed_query_string = self.check_redirect(response)
+        self.assertFalse('test' in parsed_query_string.keys())
+        self.assertFalse('_popup' in parsed_query_string.keys())
+
+
+
 class AdminInlineFileUploadTest(TestCase):
     fixtures = ['admin-views-users.xml', 'admin-views-actions.xml']
     urlbit = 'admin'
