diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index 59a4a0364d..62c5c8a782 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -420,14 +420,13 @@ class AdminSite: def catch_all_view(self, request, url): if settings.APPEND_SLASH and not url.endswith('/'): urlconf = getattr(request, 'urlconf', None) - path = '%s/' % request.path_info try: - match = resolve(path, urlconf) + match = resolve('%s/' % request.path_info, urlconf) except Resolver404: pass else: if getattr(match.func, 'should_append_slash', True): - return HttpResponsePermanentRedirect(path) + return HttpResponsePermanentRedirect('%s/' % request.path) raise Http404 def _build_app_dict(self, request, label=None): diff --git a/docs/releases/3.2.4.txt b/docs/releases/3.2.4.txt index 4ff28f9d72..51a4898163 100644 --- a/docs/releases/3.2.4.txt +++ b/docs/releases/3.2.4.txt @@ -9,4 +9,6 @@ Django 3.2.4 fixes several bugs in 3.2.3. Bugfixes ======== -* ... +* Fixed a bug in Django 3.2 where a final catch-all view in the admin didn't + respect the server-provided value of ``SCRIPT_NAME`` when redirecting + unauthenticated users to the login page (:ticket:`32754`). diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index b1658941ee..69fd43ba8f 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -6602,6 +6602,42 @@ class AdminSiteFinalCatchAllPatternTests(TestCase): response = self.client.get(known_url[:-1]) self.assertRedirects(response, known_url, status_code=301, target_status_code=403) + @override_settings(APPEND_SLASH=True) + def test_missing_slash_append_slash_true_script_name(self): + superuser = User.objects.create_user( + username='staff', + password='secret', + email='staff@example.com', + is_staff=True, + ) + self.client.force_login(superuser) + known_url = reverse('admin:admin_views_article_changelist') + response = self.client.get(known_url[:-1], SCRIPT_NAME='/prefix/') + self.assertRedirects( + response, + '/prefix' + known_url, + status_code=301, + fetch_redirect_response=False, + ) + + @override_settings(APPEND_SLASH=True, FORCE_SCRIPT_NAME='/prefix/') + def test_missing_slash_append_slash_true_force_script_name(self): + superuser = User.objects.create_user( + username='staff', + password='secret', + email='staff@example.com', + is_staff=True, + ) + self.client.force_login(superuser) + known_url = reverse('admin:admin_views_article_changelist') + response = self.client.get(known_url[:-1]) + self.assertRedirects( + response, + '/prefix' + known_url, + status_code=301, + fetch_redirect_response=False, + ) + @override_settings(APPEND_SLASH=True) def test_missing_slash_append_slash_true_non_staff_user(self): user = User.objects.create_user(