diff --git a/docs/plugins/development/views.md b/docs/plugins/development/views.md index f6624f42c13..9781cfa55a4 100644 --- a/docs/plugins/development/views.md +++ b/docs/plugins/development/views.md @@ -191,7 +191,7 @@ class MyView(generic.ObjectView): ### Extra Template Content -Plugins can inject custom content into certain areas of core NetBox views. This is accomplished by subclassing `PluginTemplateExtension`, designating a particular NetBox model, and defining the desired method(s) to render custom content. Five methods are available: +Plugins can inject custom content into certain areas of core NetBox views. This is accomplished by subclassing `PluginTemplateExtension`, optionally designating one or more particular NetBox models, and defining the desired method(s) to render custom content. Five methods are available: | Method | View | Description | |---------------------|-------------|-----------------------------------------------------| @@ -206,7 +206,9 @@ Plugins can inject custom content into certain areas of core NetBox views. This Additionally, a `render()` method is available for convenience. This method accepts the name of a template to render, and any additional context data you want to pass. Its use is optional, however. -When a PluginTemplateExtension is instantiated, context data is assigned to `self.context`. Available data include: +To control where the custom content is injected, plugin authors can specify an iterable of models by overriding the `models` attribute on the subclass. Extensions which do not specify a set of models will be invoked on every view, where supported. + +When a PluginTemplateExtension is instantiated, context data is assigned to `self.context`. Available data includes: * `object` - The object being viewed (object views only) * `model` - The model of the list view (list views only) @@ -223,7 +225,7 @@ from netbox.plugins import PluginTemplateExtension from .models import Animal class SiteAnimalCount(PluginTemplateExtension): - model = 'dcim.site' + models = ['dcim.site'] def right_page(self): return self.render('netbox_animal_sounds/inc/animal_count.html', extra_context={ diff --git a/netbox/netbox/plugins/registration.py b/netbox/netbox/plugins/registration.py index fbece12e56c..c845727942c 100644 --- a/netbox/netbox/plugins/registration.py +++ b/netbox/netbox/plugins/registration.py @@ -18,8 +18,8 @@ def register_template_extensions(class_list): """ Register a list of PluginTemplateExtension classes """ - # Validation for template_extension in class_list: + # Validation if not inspect.isclass(template_extension): raise TypeError( _("PluginTemplateExtension class {template_extension} was passed as an instance!").format( @@ -33,7 +33,17 @@ def register_template_extensions(class_list): ) ) - registry['plugins']['template_extensions'][template_extension.model].append(template_extension) + if template_extension.models: + # Registration for multiple models + models = template_extension.models + elif template_extension.model: + # Registration for a single model + models = [template_extension.model] + else: + # Global registration (no specific models) + models = [None] + for model in models: + registry['plugins']['template_extensions'][model].append(template_extension) def register_menu(menu): diff --git a/netbox/netbox/plugins/templates.py b/netbox/netbox/plugins/templates.py index ccd549160c1..5fa1959b8a7 100644 --- a/netbox/netbox/plugins/templates.py +++ b/netbox/netbox/plugins/templates.py @@ -20,6 +20,7 @@ class PluginTemplateExtension: * settings - Global NetBox settings * config - Plugin-specific configuration parameters """ + models = None model = None def __init__(self, context): diff --git a/netbox/netbox/tests/dummy_plugin/template_content.py b/netbox/netbox/tests/dummy_plugin/template_content.py index 764faa60e1c..b7157e37014 100644 --- a/netbox/netbox/tests/dummy_plugin/template_content.py +++ b/netbox/netbox/tests/dummy_plugin/template_content.py @@ -8,7 +8,7 @@ def navbar(self): class SiteContent(PluginTemplateExtension): - model = 'dcim.site' + models = ['dcim.site'] def left_page(self): return "SITE CONTENT - LEFT PAGE" diff --git a/netbox/utilities/templatetags/plugins.py b/netbox/utilities/templatetags/plugins.py index 6577843bfd7..a6e8ce84b06 100644 --- a/netbox/utilities/templatetags/plugins.py +++ b/netbox/utilities/templatetags/plugins.py @@ -22,8 +22,10 @@ def _get_registered_content(obj, method, template_context): 'perms': template_context['perms'], } - model_name = obj._meta.label_lower if obj is not None else None - template_extensions = registry['plugins']['template_extensions'].get(model_name, []) + template_extensions = registry['plugins']['template_extensions'].get(None, []) + if obj is not None: + model_name = obj._meta.label_lower + template_extensions.extend(registry['plugins']['template_extensions'].get(model_name, [])) for template_extension in template_extensions: # If the class has not overridden the specified method, we can skip it (because we know it