Просмотр исходного кода

Fixes #23227: Render datetime custom fields in local time zone (#23301)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Jeremy Stretch 23 часов назад
Родитель
Сommit
8d3d72914f
2 измененных файлов с 24 добавлено и 2 удалено
  1. 8 1
      netbox/netbox/tables/columns.py
  2. 16 1
      netbox/netbox/tests/test_tables.py

+ 8 - 1
netbox/netbox/tables/columns.py

@@ -1,5 +1,6 @@
 import zoneinfo
 from dataclasses import dataclass
+from datetime import datetime
 from urllib.parse import quote
 
 import django_tables2 as tables
@@ -22,7 +23,7 @@ from extras.choices import CustomFieldTypeChoices
 from utilities.object_types import object_type_identifier, object_type_name
 from utilities.permissions import get_permission_for_model
 from utilities.request import get_safe_request_context
-from utilities.templatetags.builtins.filters import render_markdown
+from utilities.templatetags.builtins.filters import isodatetime, render_markdown
 from utilities.validators import url_scheme_is_allowed
 from utilities.views import get_action_url
 
@@ -675,6 +676,12 @@ class CustomFieldColumn(tables.Column):
             return render_markdown(value)
         if self.customfield.type == CustomFieldTypeChoices.TYPE_DATE and value:
             return parse_date(value).isoformat()
+        if self.customfield.type == CustomFieldTypeChoices.TYPE_DATETIME and value:
+            obj = self.customfield.deserialize(value)
+            # Fall back to the raw value if it could not be parsed as a datetime
+            if isinstance(obj, datetime):
+                return isodatetime(obj)
+            return escape(obj)
         if value is not None:
             obj = self.customfield.deserialize(value)
             return mark_safe(self._linkify_item(obj))

+ 16 - 1
netbox/netbox/tests/test_tables.py

@@ -1,6 +1,7 @@
 from django.contrib.auth.models import AnonymousUser
 from django.template import Context, Template
-from django.test import RequestFactory, TestCase
+from django.test import RequestFactory, TestCase, override_settings
+from django.utils.html import strip_tags
 
 from core.models import ObjectType
 from dcim.models import Device, Site
@@ -258,3 +259,17 @@ class CustomFieldColumnTestCase(TestCase):
         # so the value has no scheme and is rendered as a link as-is.
         rendered = self._render_url('javascript%3Aalert(1)')
         self.assertEqual(rendered, '<a href="javascript%3Aalert(1)">javascript%3Aalert(1)</a>')
+
+    # A datetime custom field value must be rendered in the configured local time zone, consistent
+    # with the object's detail view (fixes #23227).
+
+    @override_settings(TIME_ZONE='Europe/Vienna')
+    def test_datetime_rendered_in_local_time_zone(self):
+        customfield = CustomField(name='datetime_field', type=CustomFieldTypeChoices.TYPE_DATETIME)
+        rendered = columns.CustomFieldColumn(customfield).render('2026-09-22T08:59:10+00:00')
+        self.assertEqual(strip_tags(rendered), '2026-09-22 10:59:10')
+
+    def test_datetime_unparseable_value_rendered_as_is(self):
+        customfield = CustomField(name='datetime_field', type=CustomFieldTypeChoices.TYPE_DATETIME)
+        rendered = columns.CustomFieldColumn(customfield).render('22/09/2026 08:59')
+        self.assertEqual(rendered, '22/09/2026 08:59')