From 61941b6fc172933f425e8ba76bab444ab9b313e4 Mon Sep 17 00:00:00 2001 From: Vedran Karacic Date: Fri, 12 Dec 2025 10:04:19 +0100 Subject: [PATCH 1/2] Fixed #35951 -- Mentioned server timezone in admin DateTime widgets. The existing note that is shown to the users when entering a time value from a different timezone than the server's timezone was not descriptive enough and led to confusion. This commit updates the note to explicitly state that the user should enter times in the server's timezone. --- .../admin/js/admin/DateTimeShortcuts.js | 20 ++++++++++++++----- .../contrib/admin/templates/admin/base.html | 5 +++-- js_tests/admin/DateTimeShortcuts.test.js | 18 +++++++++++++++-- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js b/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js index 6f71b25152bc..27223e281569 100644 --- a/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js +++ b/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js @@ -82,22 +82,32 @@ return; } + const serverTimezone = + document.body.dataset.adminServerTimezone || gettext("server"); let message; if (timezoneOffset > 0) { message = ngettext( - "Note: You are %s hour ahead of server time.", - "Note: You are %s hours ahead of server time.", + "Note: Enter times in the %(timezone)s timezone. " + + "(You are %(offset)s hour ahead.)", + "Note: Enter times in the %(timezone)s timezone. " + + "(You are %(offset)s hours ahead.)", timezoneOffset, ); } else { timezoneOffset *= -1; message = ngettext( - "Note: You are %s hour behind server time.", - "Note: You are %s hours behind server time.", + "Note: Enter times in the %(timezone)s timezone. " + + "(You are %(offset)s hour behind.)", + "Note: Enter times in the %(timezone)s timezone. " + + "(You are %(offset)s hours behind.)", timezoneOffset, ); } - message = interpolate(message, [timezoneOffset]); + message = interpolate( + message, + { timezone: serverTimezone, offset: timezoneOffset }, + true, + ); const warning = document.createElement("div"); const id = inp.id; diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html index 066f5fa65c3f..8ef92802a98f 100644 --- a/django/contrib/admin/templates/admin/base.html +++ b/django/contrib/admin/templates/admin/base.html @@ -1,4 +1,4 @@ -{% load i18n static %} +{% load i18n static tz %} {% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %} @@ -25,7 +25,8 @@ + data-admin-utc-offset="{% now "Z" %}" + data-admin-server-timezone="{% get_current_timezone as time_zone %}{{ time_zone }}"> {% translate 'Skip to main content' %}
diff --git a/js_tests/admin/DateTimeShortcuts.test.js b/js_tests/admin/DateTimeShortcuts.test.js index 5c850ce7d249..28d07fb918a3 100644 --- a/js_tests/admin/DateTimeShortcuts.test.js +++ b/js_tests/admin/DateTimeShortcuts.test.js @@ -1,7 +1,15 @@ /* global QUnit, DateTimeShortcuts */ "use strict"; -QUnit.module("admin.DateTimeShortcuts"); +QUnit.module("admin.DateTimeShortcuts", { + afterEach: function () { + const $ = django.jQuery; + $("body") + .removeAttr("data-admin-server-timezone") + .removeAttr("data-admin-utc-offset"); + $(".timezonewarning").remove(); + }, +}); QUnit.test("init", function (assert) { const $ = django.jQuery; @@ -46,11 +54,13 @@ QUnit.test("time zone offset warning - single field", function (assert) { "data-admin-utc-offset", new Date().getTimezoneOffset() * -60 + 3600, ); + $("body").attr("data-admin-server-timezone", "America/Chicago"); DateTimeShortcuts.init(); $("body").attr("data-admin-utc-offset", savedOffset); assert.equal( $(".timezonewarning").text(), - "Note: You are 1 hour behind server time.", + "Note: Enter times in the America/Chicago timezone. " + + "(You are 1 hour behind.)", ); assert.equal( $(".timezonewarning").attr("id"), @@ -74,6 +84,10 @@ QUnit.test("time zone offset warning - date and time field", function (assert) { ); DateTimeShortcuts.init(); $("body").attr("data-admin-utc-offset", savedOffset); + assert.equal( + $(".timezonewarning").text(), + "Note: Enter times in the server timezone. (You are 1 hour behind.)", + ); assert.equal( $(".timezonewarning").attr("id"), "id_updated_at_timezone_warning_helptext", From 60a9c70496e5d7b971928ce3da5b47c8836a4def Mon Sep 17 00:00:00 2001 From: Fashad Ahmed Date: Tue, 28 Apr 2026 22:38:36 +0200 Subject: [PATCH 2/2] Fixed #37067 -- Added trailing slash in django_file_prefixes(). Ensure skip_file_prefixes does not match sibling packages like django*. Bug in f42b89f1bf49a5b89ed852b60f79342320a81c5e and 34bd3ed944bf38792c631b55e581963d44d52284. --- django/utils/deprecation.py | 2 +- docs/releases/6.0.5.txt | 3 +++ tests/deprecation/tests.py | 7 ++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/django/utils/deprecation.py b/django/utils/deprecation.py index 89c9f71e5580..f85658245483 100644 --- a/django/utils/deprecation.py +++ b/django/utils/deprecation.py @@ -16,7 +16,7 @@ def django_file_prefixes(): file = getattr(django, "__file__", None) if file is None: return () - return (os.path.dirname(file),) + return (os.path.join(os.path.dirname(file), ""),) class RemovedInNextVersionWarning(DeprecationWarning): diff --git a/docs/releases/6.0.5.txt b/docs/releases/6.0.5.txt index 91443c52aebf..1e7e1b2c3b9b 100644 --- a/docs/releases/6.0.5.txt +++ b/docs/releases/6.0.5.txt @@ -14,3 +14,6 @@ Bugfixes ``django/contrib/admin/templates/admin/change_list.html`` template added in Django 6.0 that could be problematic when overriding the ``pagination`` block (:ticket:`37029`). + +* Fixed a bug in Django 6.0 where deprecation warnings incorrectly skipped + lines from third-party packages prefixed with "django" (:ticket:`37067`). diff --git a/tests/deprecation/tests.py b/tests/deprecation/tests.py index ac610b492835..0993e8a450d5 100644 --- a/tests/deprecation/tests.py +++ b/tests/deprecation/tests.py @@ -1,5 +1,6 @@ import os import warnings +from pathlib import Path import django from django.test import SimpleTestCase @@ -31,7 +32,11 @@ def test_with_file(self): prefixes = django_file_prefixes() self.assertIsInstance(prefixes, tuple) self.assertEqual(len(prefixes), 1) - self.assertTrue(prefixes[0].endswith(f"{os.path.sep}django")) + self.assertTrue(prefixes[0].endswith(f"{os.path.sep}django{os.path.sep}")) + + def test_does_not_match_packages_prefixed_with_django(self): + other_file = Path(django.__file__).parent.parent / "djangoextra" / "__init__.py" + self.assertFalse(str(other_file).startswith(django_file_prefixes())) class RenameManagerMethods(RenameMethodsBase):