added admin and api views for listing all plugins, and refactored urls import

This commit is contained in:
John Anderson
2020-03-20 20:10:02 -04:00
parent e220c38b97
commit 4e84e8048f
10 changed files with 242 additions and 39 deletions

View File

@@ -19,6 +19,7 @@ class PluginConfig(AppConfig):
"""
# Plugin metadata
author = ''
author_email = ''
description = ''
version = ''
@@ -182,7 +183,7 @@ def register_nav_menu_links():
default_app_config = getattr(module, 'default_app_config')
module, app_config = default_app_config.rsplit('.', 1)
app_config = getattr(importlib.import_module(module), app_config)
section_name = app_config.NetBoxPluginMeta.name
section_name = getattr(app_config, 'verbose_name', app_config.name)
if not isinstance(response, list):
response = [response]

View File

@@ -0,0 +1,53 @@
import importlib
from django.apps import apps
from django.conf import settings
from django.conf.urls import include
from django.core.exceptions import ImproperlyConfigured
from django.urls import path
from django.utils.module_loading import import_string
from . import views
# Plugins
plugin_patterns = []
plugin_api_patterns = []
for plugin in settings.PLUGINS:
app = apps.get_app_config(plugin)
url_slug = getattr(app, 'url_slug') or app.label
# Check if the plugin specifies any URLs
try:
urlpatterns = import_string(f"{plugin}.urls.urlpatterns")
except ImportError:
# No urls defined
urlpatterns = None
if urlpatterns:
plugin_patterns.append(
path(f"{url_slug}/", include((urlpatterns, app.label)))
)
# Check if the plugin specifies any API URLs
try:
urlpatterns = import_string(f"{plugin}.api.urls.urlpatterns")
app_name = import_string(f"{plugin}.api.urls.app_name")
except ImportError:
# No urls defined
urlpatterns = None
if urlpatterns:
plugin_api_patterns.append(
path(f"{url_slug}/", include((urlpatterns, app_name)))
)
# Plugin list admin view
admin_plugin_patterns = [
path('', views.installed_plugins_admin_view, name='plugins_list')
]
# Plugin list API view
plugin_api_patterns += [
path('', views.PluginsAPIRootView.as_view(), name='api-root'),
path('installed-plugins/', views.InstalledPluginsAPIView.as_view(), name='plugins-list')
]

View File

@@ -0,0 +1,95 @@
from collections import OrderedDict
from django.apps import apps
from django.conf import settings
from django.contrib import admin
from django.contrib.admin.views.decorators import staff_member_required
from django.urls.exceptions import NoReverseMatch
from django.utils.module_loading import import_string
from django.shortcuts import render
from django.views.generic import View
from rest_framework import authentication, permissions, routers
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.views import APIView
@staff_member_required
def installed_plugins_admin_view(request):
"""
Admin view for listing all installed plugins
"""
context_data = {
'plugins': [apps.get_app_config(plugin) for plugin in settings.PLUGINS]
}
return render(request, 'extras/admin/plugins_list.html', context_data)
class InstalledPluginsAPIView(APIView):
"""
API view for listing all installed plugins
"""
permission_classes = [permissions.IsAdminUser]
_ignore_model_permissions = True
exclude_from_schema = True
swagger_schema = None
def get_view_name(self):
return "Installed Plugins"
@staticmethod
def _get_plugin_data(plugin_app_config):
return {
'name': plugin_app_config.verbose_name,
'package': plugin_app_config.name,
'author': plugin_app_config.author,
'author_email': plugin_app_config.author_email,
'description': plugin_app_config.description,
'verison': plugin_app_config.version
}
def get(self, request, format=None):
return Response([self._get_plugin_data(apps.get_app_config(plugin)) for plugin in settings.PLUGINS])
class PluginsAPIRootView(APIView):
_ignore_model_permissions = True
exclude_from_schema = True
swagger_schema = None
def get_view_name(self):
return "Plugins"
@staticmethod
def _get_plugin_entry(plugin, app_config, request, format):
try:
api_app_name = import_string(f"{plugin}.api.urls.app_name")
except (ImportError, ModuleNotFoundError):
# Plugin does not expose an API
return None
try:
entry = (getattr(app_config, 'url_slug', app_config.label), reverse(
f"plugins-api:{api_app_name}:api-root",
request=request,
format=format
))
except NoReverseMatch:
# The plugin does not include an api-root
entry = None
return entry
def get(self, request, format=None):
entries = []
for plugin in settings.PLUGINS:
app_config = apps.get_app_config(plugin)
entry = self._get_plugin_entry(plugin, app_config, request, format)
if entry is not None:
entries.append(entry)
return Response(OrderedDict((
('installed-plugins', reverse('plugins-api:plugins-list', request=request, format=format)),
*entries
)))