From 3ac9d0b8bf839f4ccf8496012d5e6d47fb1d2d82 Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Mon, 9 Feb 2026 15:48:39 +0100 Subject: [PATCH] Closes #20981: Enhance JSON rendering for Custom Validators and Protection Rules in Config Revision View (#21376) * feat(config): Add extra context to ConfigRevisionView Introduces `get_extra_context` method for `ConfigRevisionView` to format JSON-based attributes like `CUSTOM_VALIDATORS`, `DEFAULT_USER_PREFERENCES`, and `PROTECTION_RULES`. This ensures clearer rendering of configuration data in the UI. Fixes #20981 * Reduce padding on JSON blocks --------- Co-authored-by: Jeremy Stretch --- netbox/core/views.py | 21 +++++++++++++++++++-- netbox/templates/core/configrevision.html | 2 +- netbox/templates/core/inc/config_data.html | 6 +++--- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/netbox/core/views.py b/netbox/core/views.py index c3e26ae3d..133396ac2 100644 --- a/netbox/core/views.py +++ b/netbox/core/views.py @@ -1,6 +1,7 @@ import json import platform +from copy import deepcopy from django import __version__ as django_version from django.conf import settings from django.contrib import messages @@ -310,6 +311,22 @@ class ConfigRevisionListView(generic.ObjectListView): class ConfigRevisionView(generic.ObjectView): queryset = ConfigRevision.objects.all() + def get_extra_context(self, request, instance): + """ + Retrieve additional context for a given request and instance. + """ + # Copy the revision data to avoid modifying the original + config = deepcopy(instance.data or {}) + + # Serialize any JSON-based classes + for attr in ['CUSTOM_VALIDATORS', 'DEFAULT_USER_PREFERENCES', 'PROTECTION_RULES']: + if attr in config: + config[attr] = json.dumps(config[attr], cls=ConfigJSONEncoder, indent=4) + + return { + 'config': config, + } + @register_model_view(ConfigRevision, 'add', detail=False) class ConfigRevisionEditView(generic.ObjectEditView): @@ -617,8 +634,8 @@ class SystemView(UserPassesTestMixin, View): response['Content-Disposition'] = 'attachment; filename="netbox.json"' return response - # Serialize any CustomValidator classes - for attr in ['CUSTOM_VALIDATORS', 'PROTECTION_RULES']: + # Serialize any JSON-based classes + for attr in ['CUSTOM_VALIDATORS', 'DEFAULT_USER_PREFERENCES', 'PROTECTION_RULES']: if hasattr(config, attr) and getattr(config, attr, None): setattr(config, attr, json.dumps(getattr(config, attr), cls=ConfigJSONEncoder, indent=4)) diff --git a/netbox/templates/core/configrevision.html b/netbox/templates/core/configrevision.html index ecb9f1c17..28179b7fd 100644 --- a/netbox/templates/core/configrevision.html +++ b/netbox/templates/core/configrevision.html @@ -33,7 +33,7 @@

{% trans "Configuration Data" %}

- {% include 'core/inc/config_data.html' with config=object.data %} + {% include 'core/inc/config_data.html' %}
diff --git a/netbox/templates/core/inc/config_data.html b/netbox/templates/core/inc/config_data.html index 883fa0426..cb32d7a88 100644 --- a/netbox/templates/core/inc/config_data.html +++ b/netbox/templates/core/inc/config_data.html @@ -95,7 +95,7 @@ {% trans "Custom validators" %} {% if config.CUSTOM_VALIDATORS %} -
{{ config.CUSTOM_VALIDATORS }}
+
{{ config.CUSTOM_VALIDATORS }}
{% else %} {{ ''|placeholder }} {% endif %} @@ -103,7 +103,7 @@ {% trans "Protection rules" %} {% if config.PROTECTION_RULES %} -
{{ config.PROTECTION_RULES }}
+
{{ config.PROTECTION_RULES }}
{% else %} {{ ''|placeholder }} {% endif %} @@ -116,7 +116,7 @@ {% trans "Default preferences" %} {% if config.DEFAULT_USER_PREFERENCES %} -
{{ config.DEFAULT_USER_PREFERENCES|json }}
+
{{ config.DEFAULT_USER_PREFERENCES }}
{% else %} {{ ''|placeholder }} {% endif %}