mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Closes #16359: Add navbar() method to PluginTemplateExtension
This commit is contained in:
parent
87109f5539
commit
50169365a9
@ -195,12 +195,15 @@ Plugins can inject custom content into certain areas of core NetBox views. This
|
|||||||
|
|
||||||
| Method | View | Description |
|
| Method | View | Description |
|
||||||
|---------------------|-------------|-----------------------------------------------------|
|
|---------------------|-------------|-----------------------------------------------------|
|
||||||
|
| `navbar()` | All | Inject content inside the top navigation bar |
|
||||||
| `left_page()` | Object view | Inject content on the left side of the page |
|
| `left_page()` | Object view | Inject content on the left side of the page |
|
||||||
| `right_page()` | Object view | Inject content on the right side of the page |
|
| `right_page()` | Object view | Inject content on the right side of the page |
|
||||||
| `full_width_page()` | Object view | Inject content across the entire bottom of the page |
|
| `full_width_page()` | Object view | Inject content across the entire bottom of the page |
|
||||||
| `buttons()` | Object view | Add buttons to the top of the page |
|
| `buttons()` | Object view | Add buttons to the top of the page |
|
||||||
| `list_buttons()` | List view | Add buttons to the top of the page |
|
| `list_buttons()` | List view | Add buttons to the top of the page |
|
||||||
|
|
||||||
|
!!! info "The `navbar()` method was introduced in NetBox v4.1."
|
||||||
|
|
||||||
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.
|
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:
|
When a PluginTemplateExtension is instantiated, context data is assigned to `self.context`. Available data include:
|
||||||
|
@ -32,21 +32,13 @@ def register_template_extensions(class_list):
|
|||||||
template_extension=template_extension
|
template_extension=template_extension
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if template_extension.model is None:
|
|
||||||
raise TypeError(
|
|
||||||
_("PluginTemplateExtension class {template_extension} does not define a valid model!").format(
|
|
||||||
template_extension=template_extension
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
registry['plugins']['template_extensions'][template_extension.model].append(template_extension)
|
registry['plugins']['template_extensions'][template_extension.model].append(template_extension)
|
||||||
|
|
||||||
|
|
||||||
def register_menu(menu):
|
def register_menu(menu):
|
||||||
if not isinstance(menu, PluginMenu):
|
if not isinstance(menu, PluginMenu):
|
||||||
raise TypeError(_("{item} must be an instance of netbox.plugins.PluginMenuItem").format(
|
raise TypeError(_("{item} must be an instance of netbox.plugins.PluginMenuItem").format(item=menu))
|
||||||
item=menu_link
|
|
||||||
))
|
|
||||||
registry['plugins']['menus'].append(menu)
|
registry['plugins']['menus'].append(menu)
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ class PluginTemplateExtension:
|
|||||||
The `model` attribute on the class defines the which model detail page this class renders content for. It
|
The `model` attribute on the class defines the which model detail page this class renders content for. It
|
||||||
should be set as a string in the form '<app_label>.<model_name>'. render() provides the following context data:
|
should be set as a string in the form '<app_label>.<model_name>'. render() provides the following context data:
|
||||||
|
|
||||||
* object - The object being viewed
|
* object - The object being viewed (object views only)
|
||||||
|
* model - The type of object being viewed (list views only)
|
||||||
* request - The current request
|
* request - The current request
|
||||||
* settings - Global NetBox settings
|
* settings - Global NetBox settings
|
||||||
* config - Plugin-specific configuration parameters
|
* config - Plugin-specific configuration parameters
|
||||||
@ -36,6 +37,13 @@ class PluginTemplateExtension:
|
|||||||
|
|
||||||
return get_template(template_name).render({**self.context, **extra_context})
|
return get_template(template_name).render({**self.context, **extra_context})
|
||||||
|
|
||||||
|
def navbar(self):
|
||||||
|
"""
|
||||||
|
Content that will be rendered inside the top navigation menu. Content should be returned as an HTML
|
||||||
|
string. Note that content does not need to be marked as safe because this is automatically handled.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def left_page(self):
|
def left_page(self):
|
||||||
"""
|
"""
|
||||||
Content that will be rendered on the left of the detail page view. Content should be returned as an
|
Content that will be rendered on the left of the detail page view. Content should be returned as an
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
from netbox.plugins.templates import PluginTemplateExtension
|
from netbox.plugins.templates import PluginTemplateExtension
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalContent(PluginTemplateExtension):
|
||||||
|
|
||||||
|
def navbar(self):
|
||||||
|
return "GLOBAL CONTENT - NAVBAR"
|
||||||
|
|
||||||
|
|
||||||
class SiteContent(PluginTemplateExtension):
|
class SiteContent(PluginTemplateExtension):
|
||||||
model = 'dcim.site'
|
model = 'dcim.site'
|
||||||
|
|
||||||
@ -20,4 +26,4 @@ class SiteContent(PluginTemplateExtension):
|
|||||||
return "SITE CONTENT - LIST BUTTONS"
|
return "SITE CONTENT - LIST BUTTONS"
|
||||||
|
|
||||||
|
|
||||||
template_extensions = [SiteContent]
|
template_extensions = [GlobalContent, SiteContent]
|
||||||
|
@ -99,8 +99,9 @@ class PluginTest(TestCase):
|
|||||||
"""
|
"""
|
||||||
Check that plugin TemplateExtensions are registered.
|
Check that plugin TemplateExtensions are registered.
|
||||||
"""
|
"""
|
||||||
from netbox.tests.dummy_plugin.template_content import SiteContent
|
from netbox.tests.dummy_plugin.template_content import GlobalContent, SiteContent
|
||||||
|
|
||||||
|
self.assertIn(GlobalContent, registry['plugins']['template_extensions'][None])
|
||||||
self.assertIn(SiteContent, registry['plugins']['template_extensions']['dcim.site'])
|
self.assertIn(SiteContent, registry['plugins']['template_extensions']['dcim.site'])
|
||||||
|
|
||||||
def test_registered_columns(self):
|
def test_registered_columns(self):
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
{% extends 'base/base.html' %}
|
{% extends 'base/base.html' %}
|
||||||
{% load helpers %}
|
{% load helpers %}
|
||||||
{% load navigation %}
|
{% load navigation %}
|
||||||
|
{% load plugins %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
@ -51,8 +52,12 @@ Blocks:
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
|
||||||
<div class="navbar-nav flex-row align-items-center order-md-last">
|
<div class="navbar-nav flex-row align-items-center order-md-last">
|
||||||
|
|
||||||
|
{# Plugin content #}
|
||||||
|
{% plugin_navbar %}
|
||||||
|
|
||||||
{# Dark/light mode toggle #}
|
{# Dark/light mode toggle #}
|
||||||
<div class="d-none d-md-flex">
|
<div class="d-none d-md-flex ms-2">
|
||||||
<button class="btn color-mode-toggle hide-theme-dark" title="{% trans "Enable dark mode" %}" data-bs-toggle="tooltip" data-bs-placement="bottom">
|
<button class="btn color-mode-toggle hide-theme-dark" title="{% trans "Enable dark mode" %}" data-bs-toggle="tooltip" data-bs-placement="bottom">
|
||||||
<i class="mdi mdi-lightbulb"></i>
|
<i class="mdi mdi-lightbulb"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -22,7 +22,7 @@ def _get_registered_content(obj, method, template_context):
|
|||||||
'perms': template_context['perms'],
|
'perms': template_context['perms'],
|
||||||
}
|
}
|
||||||
|
|
||||||
model_name = obj._meta.label_lower
|
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(model_name, [])
|
||||||
for template_extension in template_extensions:
|
for template_extension in template_extensions:
|
||||||
|
|
||||||
@ -43,6 +43,14 @@ def _get_registered_content(obj, method, template_context):
|
|||||||
return mark_safe(html)
|
return mark_safe(html)
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag(takes_context=True)
|
||||||
|
def plugin_navbar(context):
|
||||||
|
"""
|
||||||
|
Render any navbar content embedded by plugins
|
||||||
|
"""
|
||||||
|
return _get_registered_content(None, 'navbar', context)
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def plugin_buttons(context, obj):
|
def plugin_buttons(context, obj):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user