#19773: Include Django apps in system status view

This commit is contained in:
Jeremy Stretch 2025-08-13 09:03:16 -04:00
parent 2004ab7a0e
commit b5b0c40727
4 changed files with 60 additions and 21 deletions

View File

@ -27,6 +27,7 @@ from netbox.plugins.utils import get_installed_plugins
from netbox.views import generic from netbox.views import generic
from netbox.views.generic.base import BaseObjectView from netbox.views.generic.base import BaseObjectView
from netbox.views.generic.mixins import TableMixin from netbox.views.generic.mixins import TableMixin
from utilities.apps import get_installed_apps
from utilities.data import shallow_compare_dict from utilities.data import shallow_compare_dict
from utilities.forms import ConfirmationForm from utilities.forms import ConfirmationForm
from utilities.htmx import htmx_partial from utilities.htmx import htmx_partial
@ -575,6 +576,9 @@ class SystemView(UserPassesTestMixin, View):
'rq_worker_count': Worker.count(get_connection('default')), 'rq_worker_count': Worker.count(get_connection('default')),
} }
# Django apps
django_apps = get_installed_apps()
# Configuration # Configuration
config = get_config() config = get_config()
@ -593,6 +597,7 @@ class SystemView(UserPassesTestMixin, View):
params = [param.name for param in PARAMS] params = [param.name for param in PARAMS]
data = { data = {
**stats, **stats,
'django_apps': django_apps,
'plugins': plugins, 'plugins': plugins,
'config': { 'config': {
k: getattr(config, k) for k in sorted(params) k: getattr(config, k) for k in sorted(params)
@ -612,6 +617,7 @@ class SystemView(UserPassesTestMixin, View):
return render(request, 'core/system.html', { return render(request, 'core/system.html', {
'stats': stats, 'stats': stats,
'django_apps': django_apps,
'config': config, 'config': config,
'plugins': plugins, 'plugins': plugins,
'objects': objects, 'objects': objects,

View File

@ -1,7 +1,6 @@
import platform import platform
from django import __version__ as DJANGO_VERSION from django import __version__ as DJANGO_VERSION
from django.apps import apps
from django.conf import settings from django.conf import settings
from django_rq.queues import get_connection from django_rq.queues import get_connection
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
@ -13,6 +12,7 @@ from rq.worker import Worker
from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
from netbox.plugins.utils import get_installed_plugins from netbox.plugins.utils import get_installed_plugins
from utilities.apps import get_installed_apps
class APIRootView(APIView): class APIRootView(APIView):
@ -52,21 +52,10 @@ class StatusView(APIView):
@extend_schema(responses={200: OpenApiTypes.OBJECT}) @extend_schema(responses={200: OpenApiTypes.OBJECT})
def get(self, request): 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({ return Response({
'django-version': DJANGO_VERSION, 'django-version': DJANGO_VERSION,
'hostname': settings.HOSTNAME, 'hostname': settings.HOSTNAME,
'installed-apps': installed_apps, 'installed_apps': get_installed_apps(),
'netbox-version': settings.RELEASE.version, 'netbox-version': settings.RELEASE.version,
'netbox-full-version': settings.RELEASE.full_version, 'netbox-full-version': settings.RELEASE.full_version,
'plugins': get_installed_plugins(), 'plugins': get_installed_plugins(),

View File

@ -45,6 +45,10 @@
<div class="card"> <div class="card">
<h2 class="card-header">{% trans "System Status" %}</h2> <h2 class="card-header">{% trans "System Status" %}</h2>
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
<tr>
<th scope="row">{% trans "System hostname" %}</th>
<td>{{ settings.HOSTNAME }}</td>
</tr>
<tr> <tr>
<th scope="row">{% trans "NetBox release" %}</th> <th scope="row">{% trans "NetBox release" %}</th>
<td> <td>
@ -93,6 +97,23 @@
</tr> </tr>
</table> </table>
</div> </div>
<div class="card">
<h2 class="card-header">{% trans "Django Apps" %}</h2>
{% if django_apps %}
<table class="table table-hover attr-table">
{% for app_name, version in django_apps.items %}
<tr>
<td>{{ app_name }}</td>
<td>{{ version }}</td>
</tr>
{% endfor %}
</table>
{% else %}
<div class="card-body text-muted">
{% trans "None found" %}
</div>
{% endif %}
</div>
</div> </div>
</div> </div>
</div> </div>
@ -115,14 +136,20 @@
<div class="col"> <div class="col">
<div class="card"> <div class="card">
<h2 class="card-header">{% trans "Installed Plugins" %}</h2> <h2 class="card-header">{% trans "Installed Plugins" %}</h2>
<table class="table table-hover attr-table"> {% if plugins %}
{% for plugin, version in plugins.items %} <table class="table table-hover attr-table">
<tr> {% for plugin, version in plugins.items %}
<td>{{ plugin }}</td> <tr>
<td>{{ version }}</td> <td>{{ plugin }}</td>
</tr> <td>{{ version }}</td>
{% endfor %} </tr>
</table> {% endfor %}
</table>
{% else %}
<div class="card-body text-muted">
{% trans "No plugins are installed." %}
</div>
{% endif %}
</div> </div>
</div> </div>
</div> </div>

17
netbox/utilities/apps.py Normal file
View File

@ -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())
}