From b5b0c407276e83bd39902c73dea772e0b5aa4536 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 13 Aug 2025 09:03:16 -0400 Subject: [PATCH] #19773: Include Django apps in system status view --- netbox/core/views.py | 6 +++++ netbox/netbox/api/views.py | 15 ++--------- netbox/templates/core/system.html | 43 +++++++++++++++++++++++++------ netbox/utilities/apps.py | 17 ++++++++++++ 4 files changed, 60 insertions(+), 21 deletions(-) create mode 100644 netbox/utilities/apps.py diff --git a/netbox/core/views.py b/netbox/core/views.py index 9d9d6e2be..b18937308 100644 --- a/netbox/core/views.py +++ b/netbox/core/views.py @@ -27,6 +27,7 @@ from netbox.plugins.utils import get_installed_plugins from netbox.views import generic from netbox.views.generic.base import BaseObjectView from netbox.views.generic.mixins import TableMixin +from utilities.apps import get_installed_apps from utilities.data import shallow_compare_dict from utilities.forms import ConfirmationForm from utilities.htmx import htmx_partial @@ -575,6 +576,9 @@ class SystemView(UserPassesTestMixin, View): 'rq_worker_count': Worker.count(get_connection('default')), } + # Django apps + django_apps = get_installed_apps() + # Configuration config = get_config() @@ -593,6 +597,7 @@ class SystemView(UserPassesTestMixin, View): params = [param.name for param in PARAMS] data = { **stats, + 'django_apps': django_apps, 'plugins': plugins, 'config': { k: getattr(config, k) for k in sorted(params) @@ -612,6 +617,7 @@ class SystemView(UserPassesTestMixin, View): return render(request, 'core/system.html', { 'stats': stats, + 'django_apps': django_apps, 'config': config, 'plugins': plugins, 'objects': objects, diff --git a/netbox/netbox/api/views.py b/netbox/netbox/api/views.py index 82124e1c5..6740700b8 100644 --- a/netbox/netbox/api/views.py +++ b/netbox/netbox/api/views.py @@ -1,7 +1,6 @@ import platform from django import __version__ as DJANGO_VERSION -from django.apps import apps from django.conf import settings from django_rq.queues import get_connection from drf_spectacular.types import OpenApiTypes @@ -13,6 +12,7 @@ from rq.worker import Worker from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired from netbox.plugins.utils import get_installed_plugins +from utilities.apps import get_installed_apps class APIRootView(APIView): @@ -52,21 +52,10 @@ class StatusView(APIView): @extend_schema(responses={200: OpenApiTypes.OBJECT}) def get(self, request): - # Gather the version numbers from all installed Django apps - installed_apps = {} - for app_config in apps.get_app_configs(): - app = app_config.module - version = getattr(app, 'VERSION', getattr(app, '__version__', None)) - if version: - if type(version) is tuple: - version = '.'.join(str(n) for n in version) - installed_apps[app_config.name] = version - installed_apps = {k: v for k, v in sorted(installed_apps.items())} - return Response({ 'django-version': DJANGO_VERSION, 'hostname': settings.HOSTNAME, - 'installed-apps': installed_apps, + 'installed_apps': get_installed_apps(), 'netbox-version': settings.RELEASE.version, 'netbox-full-version': settings.RELEASE.full_version, 'plugins': get_installed_plugins(), diff --git a/netbox/templates/core/system.html b/netbox/templates/core/system.html index 1e2914b3c..092bc708d 100644 --- a/netbox/templates/core/system.html +++ b/netbox/templates/core/system.html @@ -45,6 +45,10 @@

{% trans "System Status" %}

+ + + +
{% trans "System hostname" %}{{ settings.HOSTNAME }}
{% trans "NetBox release" %} @@ -93,6 +97,23 @@
+
+

{% trans "Django Apps" %}

+ {% if django_apps %} + + {% for app_name, version in django_apps.items %} + + + + + {% endfor %} +
{{ app_name }}{{ version }}
+ {% else %} +
+ {% trans "None found" %} +
+ {% endif %} +
@@ -115,14 +136,20 @@

{% trans "Installed Plugins" %}

- - {% for plugin, version in plugins.items %} - - - - - {% endfor %} -
{{ plugin }}{{ version }}
+ {% if plugins %} + + {% for plugin, version in plugins.items %} + + + + + {% endfor %} +
{{ plugin }}{{ version }}
+ {% else %} +
+ {% trans "No plugins are installed." %} +
+ {% endif %}
diff --git a/netbox/utilities/apps.py b/netbox/utilities/apps.py new file mode 100644 index 000000000..b5445c8c4 --- /dev/null +++ b/netbox/utilities/apps.py @@ -0,0 +1,17 @@ +from django.apps import apps + + +def get_installed_apps(): + """ + Return the name and version number for each installed Django app. + """ + installed_apps = {} + for app_config in apps.get_app_configs(): + app = app_config.module + if version := getattr(app, 'VERSION', getattr(app, '__version__', None)): + if type(version) is tuple: + version = '.'.join(str(n) for n in version) + installed_apps[app_config.name] = version + return { + k: v for k, v in sorted(installed_apps.items()) + }