diff --git a/docs/plugins/development.md b/docs/plugins/development.md index 402c047e6..84d04bc8e 100644 --- a/docs/plugins/development.md +++ b/docs/plugins/development.md @@ -325,13 +325,17 @@ Plugins can inject custom content into certain areas of the detail views of appl * `full_width_page()` - Inject content across the entire bottom of the page * `buttons()` - Add buttons to the top of the page -Each of these methods must return HTML content suitable for inclusion in the object template. Two instance attributes are available for context: - -* `self.obj` - The object being viewed -* `self.context` - The current template context - 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: + +* `obj` - The object being viewed +* `request` - The current request +* `settings` - Global NetBox settings +* `config` - Plugin-specific configuration parameters + +For example, accessing `{{ request.user }}` within a template will return the current user. + Declared subclasses should be gathered into a list or tuple for integration with NetBox. By default, NetBox looks for an iterable named `template_extensions` within a `template_content.py` file. (This can be overridden by setting `template_extensions` to a custom value on the plugin's PluginConfig.) An example is below. ```python diff --git a/netbox/extras/plugins/__init__.py b/netbox/extras/plugins/__init__.py index bcd57d767..30a4e0acd 100644 --- a/netbox/extras/plugins/__init__.py +++ b/netbox/extras/plugins/__init__.py @@ -83,8 +83,7 @@ class PluginTemplateExtension: """ model = None - def __init__(self, obj, context): - self.obj = obj + def __init__(self, context): self.context = context def render(self, template, extra_context=None): @@ -93,14 +92,12 @@ class PluginTemplateExtension: passed into the template context as `obj` and the original detail page's context is available as `obj_context`. An additional context dictionary may be passed as `extra_context`. """ - context = { - 'obj': self.obj, - 'obj_context': self.context - } - if isinstance(extra_context, dict): - context.update(extra_context) + if extra_context is None: + extra_context = {} + elif not isinstance(extra_context, dict): + raise TypeError("extra_context must be a dictionary") - return get_template(template).render(context) + return get_template(template).render({**self.context, **extra_context}) def left_page(self): """ diff --git a/netbox/extras/templatetags/plugins.py b/netbox/extras/templatetags/plugins.py index 5fa3b4ce2..63c126fc8 100644 --- a/netbox/extras/templatetags/plugins.py +++ b/netbox/extras/templatetags/plugins.py @@ -1,4 +1,5 @@ from django import template as template_ +from django.conf import settings from django.utils.safestring import mark_safe from extras.registry import registry @@ -6,18 +7,30 @@ from extras.registry import registry register = template_.Library() -def _get_registered_content(obj, method, context): +def _get_registered_content(obj, method, template_context): """ Given an object and a PluginTemplateExtension method name and the template context, return all the registered content for the object's model. """ html = '' + context = { + 'obj': obj, + 'request': template_context['request'], + 'settings': template_context['settings'], + 'config': {}, # Defined per-plugin + } model_name = obj._meta.label_lower - for template_extension_class in registry['plugin_template_extensions'].get(model_name, []): - template_extension_instance = template_extension_class(obj, context) + template_extensions = registry['plugin_template_extensions'].get(model_name, []) + for template_extension in template_extensions: + + # Update context with plugin-specific configuration parameters + plugin_name = template_extension.__module__.split('.')[0] + context['config'] = settings.PLUGINS_CONFIG.get(plugin_name) + + instance = template_extension(context) try: - content = getattr(template_extension_instance, method)() + content = getattr(instance, method)() except NotImplementedError: # This content renderer class does not define content for this method continue