Coverage for utilities/templatetags/plugins.py: 61%
50 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
1from django import template as template_
2from django.conf import settings
3from django.template.loader import render_to_string
4from django.utils.safestring import mark_safe
6from netbox.plugins import PluginTemplateExtension
7from netbox.registry import registry
9register = template_.Library()
12def _get_registered_content(obj, method, template_context):
13 """
14 Given an object and a PluginTemplateExtension method name and the template context, return all the
15 registered content for the object's model.
16 """
17 html = ''
18 context = {
19 'object': obj,
20 'request': template_context['request'],
21 'settings': template_context['settings'],
22 'csrf_token': template_context['csrf_token'],
23 'perms': template_context['perms'],
24 }
26 template_extensions = list(registry['plugins']['template_extensions'].get(None, []))
27 if hasattr(obj, '_meta'): 27 ↛ 28line 27 didn't jump to line 28 because the condition on line 27 was never true
28 model_name = obj._meta.label_lower
29 template_extensions.extend(registry['plugins']['template_extensions'].get(model_name, []))
30 for template_extension in template_extensions: 30 ↛ 34line 30 didn't jump to line 34 because the loop on line 30 never started
32 # If the class has not overridden the specified method, we can skip it (because we know it
33 # will raise NotImplementedError).
34 if getattr(template_extension, method) == getattr(PluginTemplateExtension, method):
35 continue
37 # Update context with plugin-specific configuration parameters
38 plugin_name = template_extension.__module__.split('.')[0]
39 context['config'] = settings.PLUGINS_CONFIG.get(plugin_name, {})
41 # Call the method to render content
42 try:
43 instance = template_extension(context)
44 content = getattr(instance, method)()
45 except Exception as e:
46 content = render_to_string('ui/exception.html', {'plugin': plugin_name, 'exception': repr(e)})
47 html += content
49 return mark_safe(html)
52@register.simple_tag(takes_context=True)
53def plugin_head(context):
54 """
55 Render any <head> content embedded by plugins
56 """
57 return _get_registered_content(None, 'head', context)
60@register.simple_tag(takes_context=True)
61def plugin_navbar(context):
62 """
63 Render any navbar content embedded by plugins
64 """
65 return _get_registered_content(None, 'navbar', context)
68@register.simple_tag(takes_context=True)
69def plugin_list_buttons(context, model):
70 """
71 Render all list buttons registered by plugins
72 """
73 return _get_registered_content(model, 'list_buttons', context)
76@register.simple_tag(takes_context=True)
77def plugin_buttons(context, obj):
78 """
79 Render all buttons registered by plugins
80 """
81 return _get_registered_content(obj, 'buttons', context)
84@register.simple_tag(takes_context=True)
85def plugin_alerts(context, obj):
86 """
87 Render all object alerts registered by plugins
88 """
89 return _get_registered_content(obj, 'alerts', context)
92@register.simple_tag(takes_context=True)
93def plugin_left_page(context, obj):
94 """
95 Render all left page content registered by plugins
96 """
97 return _get_registered_content(obj, 'left_page', context)
100@register.simple_tag(takes_context=True)
101def plugin_right_page(context, obj):
102 """
103 Render all right page content registered by plugins
104 """
105 return _get_registered_content(obj, 'right_page', context)
108@register.simple_tag(takes_context=True)
109def plugin_full_width_page(context, obj):
110 """
111 Render all full width page content registered by plugins
112 """
113 return _get_registered_content(obj, 'full_width_page', context)