From e92d1e3b7858981185e93d717c5727544d66b66e Mon Sep 17 00:00:00 2001 From: Nilesh Kumar Pahari Date: Tue, 13 Jan 2026 00:39:48 +0530 Subject: [PATCH 1/3] Fixed #36850 -- Prevented admin filter sidebar from wrapping below the changelist. Removed flex-wrap from .changelist-form-container and added min-width to the main content container to ensure proper layout behavior. Regression in 6ea331907996a51842da55c1f8d65eea7b367c7d. --- .../admin/static/admin/css/changelists.css | 2 +- docs/releases/6.0.2.txt | 5 ++++- tests/admin_views/models.py | 8 +++++++- tests/admin_views/tests.py | 15 +++++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/django/contrib/admin/static/admin/css/changelists.css b/django/contrib/admin/static/admin/css/changelists.css index 3557097292cd..1b23f145dcbd 100644 --- a/django/contrib/admin/static/admin/css/changelists.css +++ b/django/contrib/admin/static/admin/css/changelists.css @@ -2,7 +2,6 @@ #changelist .changelist-form-container { display: flex; - flex-wrap: wrap; align-items: flex-start; width: 100%; } @@ -16,6 +15,7 @@ } #changelist .changelist-form-container:has(#changelist-filter) > div { + min-width: 0; max-width: calc(100% - 270px); } diff --git a/docs/releases/6.0.2.txt b/docs/releases/6.0.2.txt index c708f699bb04..c437275f3f92 100644 --- a/docs/releases/6.0.2.txt +++ b/docs/releases/6.0.2.txt @@ -9,4 +9,7 @@ Django 6.0.2 fixes several bugs in 6.0.1. Bugfixes ======== -* ... +* Fixed a visual regression in Django 6.0 that caused the admin filter sidebar + to wrap below the changelist when filter elements contained long text + (:ticket:`36850`). + diff --git a/tests/admin_views/models.py b/tests/admin_views/models.py index 4e2d13efa827..fe127f57d37f 100644 --- a/tests/admin_views/models.py +++ b/tests/admin_views/models.py @@ -266,7 +266,13 @@ class Person(models.Model): (2, "Female"), ) name = models.CharField(max_length=100) - gender = models.IntegerField(choices=GENDER_CHOICES) + gender = models.IntegerField( + choices=GENDER_CHOICES, + verbose_name=( + "very very very very very very very very very " + "loooooooooooooooooooooooooooooooooooooooooong name" + ), + ) age = models.IntegerField(default=21) alive = models.BooleanField(default=True) diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index 3377a6d44177..ad64762a5192 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -7205,6 +7205,21 @@ def test_pagination_layout(self): self.assertTrue(show_all.is_displayed()) self.take_screenshot("pagination") + @screenshot_cases(["desktop_size", "mobile_size", "rtl", "dark", "high_contrast"]) + def test_changelist_filter_sidebar_with_long_verbose_fields(self): + from selenium.webdriver.common.by import By + + self.admin_login( + username="super", password="secret", login_url=reverse("admin:index") + ) + Person.objects.create(name="John", gender=1) + self.selenium.get( + self.live_server_url + reverse("admin:admin_views_person_changelist") + ) + changelist_filter = self.selenium.find_element(By.ID, "changelist-filter") + self.assertTrue(changelist_filter.is_displayed()) + self.take_screenshot("filter_sidebar") + @override_settings(ROOT_URLCONF="admin_views.urls") class ReadonlyTest(AdminFieldExtractionMixin, TestCase): From 229d026207dddd5b184e9569f104d315f1c79c81 Mon Sep 17 00:00:00 2001 From: varunkasyap Date: Sun, 25 Jan 2026 11:02:09 +0530 Subject: [PATCH 2/3] Fixed #36883 -- Split monolithic aggregation regression tests. --- tests/aggregation_regress/tests.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/aggregation_regress/tests.py b/tests/aggregation_regress/tests.py index c7d9271dd8ae..1140022b4c3c 100644 --- a/tests/aggregation_regress/tests.py +++ b/tests/aggregation_regress/tests.py @@ -849,7 +849,7 @@ def test_empty(self): ], ) - def test_more_more(self): + def test_order_by_group_by_join(self): # Regression for #10113 - Fields mentioned in order_by() must be # included in the GROUP BY. This only becomes a problem when the # order_by introduces a new join. @@ -869,6 +869,7 @@ def test_more_more(self): lambda b: b.name, ) + def test_annotate_select_related(self): # Regression for #10127 - Empty select_related() works with annotate qs = ( Book.objects.filter(rating__lt=4.5) @@ -897,6 +898,7 @@ def test_more_more(self): lambda b: (b.name, b.authors__age__avg, b.publisher.name, b.contact.name), ) + def test_values_extra_grouping(self): # Regression for #10132 - If the values() clause only mentioned extra # (select=) columns, those columns are used for grouping qs = ( @@ -931,6 +933,7 @@ def test_more_more(self): ], ) + def test_aggregate_subquery_annotation(self): # Regression for #10182 - Queries with aggregate calls are correctly # realiased when used in a subquery ids = ( @@ -947,6 +950,7 @@ def test_more_more(self): lambda b: b.name, ) + def test_group_by_field_uniqueness(self): # Regression for #15709 - Ensure each group_by field only exists once # per query qstr = str( @@ -1046,7 +1050,7 @@ def test_pickle(self): query, ) - def test_more_more_more(self): + def test_aggregate_cloning(self): # Regression for #10199 - Aggregate calls clone the original query so # the original query can still be used books = Book.objects.all() @@ -1065,6 +1069,7 @@ def test_more_more_more(self): lambda b: b.name, ) + def test_annotate_with_dates(self): # Regression for #10248 - Annotations work with dates() qs = ( Book.objects.annotate(num_authors=Count("authors")) @@ -1079,6 +1084,7 @@ def test_more_more_more(self): ], ) + def test_extra_select_grouping_with_params(self): # Regression for #10290 - extra selects with parameters can be used for # grouping. qs = ( @@ -1091,6 +1097,7 @@ def test_more_more_more(self): qs, [150, 175, 224, 264, 473, 566], lambda b: int(b["sheets"]) ) + def test_annotate_and_count(self): # Regression for 10425 - annotations don't get in the way of a count() # clause self.assertEqual( @@ -1100,6 +1107,7 @@ def test_more_more_more(self): Book.objects.annotate(Count("publisher")).values("publisher").count(), 6 ) + def test_annotate_ordering_by_annotation_and_filtering(self): # Note: intentionally no order_by(), that case needs tests, too. publishers = Publisher.objects.filter(id__in=[self.p1.id, self.p2.id]) self.assertEqual(sorted(p.name for p in publishers), ["Apress", "Sams"]) @@ -1123,6 +1131,7 @@ def test_more_more_more(self): ) self.assertEqual(sorted(p.name for p in publishers), ["Apress", "Sams"]) + def test_inherited_fields_aggregation(self): # Regression for 10666 - inherited fields work with annotations and # aggregations self.assertEqual( @@ -1175,6 +1184,7 @@ def test_more_more_more(self): ], ) + def test_aggregate_referencing_aggregate(self): # Regression for #10766 - Shouldn't be able to reference an aggregate # fields in an aggregate() call. msg = "Cannot compute Avg('mean_age'): 'mean_age' is an aggregate" From 2e83eb5e78e8036141ae5b810fba4fd9e800f51f Mon Sep 17 00:00:00 2001 From: jafarkhan83 Date: Mon, 26 Jan 2026 14:26:00 +0500 Subject: [PATCH 3/3] Fixed #36776 -- Clarified dev server runs in WSGI mode. --- django/core/management/commands/runserver.py | 3 ++- tests/admin_scripts/tests.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/django/core/management/commands/runserver.py b/django/core/management/commands/runserver.py index 0cf841b747f1..292e744d7282 100644 --- a/django/core/management/commands/runserver.py +++ b/django/core/management/commands/runserver.py @@ -184,7 +184,8 @@ def on_bind(self, server_port): print( f"{now}\n" f"Django version {version}, using settings {settings.SETTINGS_MODULE!r}\n" - f"Starting development server at {self.protocol}://{addr}:{server_port}/\n" + f"Starting WSGI development server at {self.protocol}://{addr}" + f":{server_port}/\n" f"Quit the server with {quit_command}.", file=self.stdout, ) diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py index 19ef99ac49e6..3b5b0380f0f9 100644 --- a/tests/admin_scripts/tests.py +++ b/tests/admin_scripts/tests.py @@ -1624,7 +1624,7 @@ def test_zero_ip_addr(self): self.cmd._raw_ipv6 = False self.cmd.on_bind("8000") self.assertIn( - "Starting development server at http://0.0.0.0:8000/", + "Starting WSGI development server at http://0.0.0.0:8000/", self.output.getvalue(), ) docs_version = get_docs_version() @@ -1643,7 +1643,7 @@ def test_on_bind(self): self.cmd._raw_ipv6 = False self.cmd.on_bind("14437") self.assertIn( - "Starting development server at http://127.0.0.1:14437/", + "Starting WSGI development server at http://127.0.0.1:14437/", self.output.getvalue(), ) docs_version = get_docs_version() @@ -1662,7 +1662,7 @@ def test_hide_production_warning_with_environment_variable(self): self.cmd._raw_ipv6 = False self.cmd.on_bind("8000") self.assertIn( - "Starting development server at http://0.0.0.0:8000/", + "Starting WSGI development server at http://0.0.0.0:8000/", self.output.getvalue(), ) docs_version = get_docs_version()