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

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 

5 

6from netbox.plugins import PluginTemplateExtension 

7from netbox.registry import registry 

8 

9register = template_.Library() 

10 

11 

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 } 

25 

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

31 

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 

36 

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, {}) 

40 

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 

48 

49 return mark_safe(html) 

50 

51 

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) 

58 

59 

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) 

66 

67 

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) 

74 

75 

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) 

82 

83 

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) 

90 

91 

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) 

98 

99 

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) 

106 

107 

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)