Просмотр исходного кода

Restrict context data available to PluginTemplateExtensions

Jeremy Stretch 5 лет назад
Родитель
Сommit
f03cc96050

+ 8 - 4
docs/plugins/development.md

@@ -325,12 +325,16 @@ 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:
+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.
 
-* `self.obj` - The object being viewed
-* `self.context` - The current template context
+When a PluginTemplateExtension is instantiated, context data is assigned to `self.context`. Available data include:
 
-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.
+* `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.
 

+ 7 - 10
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)
-
-        return get_template(template).render(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({**self.context, **extra_context})
 
     def left_page(self):
         """

+ 17 - 4
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