Преглед изворни кода

added plugin template content injection to primary model detail views

John Anderson пре 6 година
родитељ
комит
8364694fb4

+ 87 - 0
netbox/extras/plugins/__init__.py

@@ -0,0 +1,87 @@
+import collections
+import inspect
+
+from django.core.exceptions import ImproperlyConfigured
+from django.template.loader import get_template
+
+from extras.utils import registry
+from .signals import register_detail_page_content_classes
+
+
+class PluginTemplateContent:
+    """
+    This class is used to register plugin content to be injected into core NetBox templates.
+    It contains methods that are overriden by plugin authors to return template content.
+
+    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>'.
+    """
+    model = None
+
+    def __init__(self, obj):
+        self.obj = obj
+
+    def render(self, template, extra_context=None):
+        """
+        Convenience menthod for rendering the provided template name. The detail page object is automatically
+        passed into the template context as `obj` but an additional context dictionary may be passed as `extra_context`.
+        """
+        context = {'obj': self.obj}
+        if isinstance(extra_context, dict):
+            context.update(extra_context)
+
+        return get_template(template).render(context)
+
+    def left_page(self):
+        """
+        Content that will be rendered on the left of the detail page view. 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 right_page(self):
+        """
+        Content that will be rendered on the right of the detail page view. 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 full_width_page(self):
+        """
+        Content that will be rendered within the full width of the detail page view. 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 buttons(self):
+        """
+        Buttons that will be rendered and added to the existing list of buttons on the detail page view. 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 register_content_classes():
+    registry.plugin_template_content_classes = collections.defaultdict(list)
+
+    responses = register_detail_page_content_classes.send('registration_event')
+    for receiver, response in responses:
+        if not isinstance(response, list):
+            response = [response]
+        for template_class in response:
+            if not inspect.isclass(template_class):
+                raise TypeError('Plugin content class {} was passes as an instance!'.format(template_class))
+            if not issubclass(template_class, PluginTemplateContent):
+                raise TypeError('{} is not a subclass of extras.plugins.PluginTemplateContent!'.format(template_class))
+            if template_class.model is None:
+                raise TypeError('Plugin content class {} does not define a valid model!'.format(template_class))
+
+            registry.plugin_template_content_classes[template_class.model].append(template_class)
+
+
+def get_content_classes(model):
+    if not hasattr(registry, 'plugin_template_content_classes'):
+        register_content_classes()
+
+    return registry.plugin_template_content_classes.get(model, [])

+ 2 - 2
netbox/extras/plugins/signals.py

@@ -27,8 +27,8 @@ class PluginSignal(django.dispatch.Signal):
 
 
 
 
 """
 """
-This signal collects templates which render buttons for object detail pages
+This signal collects templates which render content for object detail pages
 """
 """
-register_detail_page_buttons = PluginSignal(
+register_detail_page_content_classes = PluginSignal(
     providing_args=[]
     providing_args=[]
 )
 )

+ 0 - 0
netbox/extras/plugins/templatetags/__init__.py


+ 44 - 11
netbox/extras/templatetags/plugins.py

@@ -2,26 +2,59 @@ from django import template as template_
 from django.template.loader import get_template
 from django.template.loader import get_template
 from django.utils.safestring import mark_safe
 from django.utils.safestring import mark_safe
 
 
-from extras.plugins.signals import register_detail_page_buttons
+from extras.plugins import get_content_classes
 
 
 
 
 register = template_.Library()
 register = template_.Library()
 
 
 
 
+def _get_registered_content(obj, method):
+    """
+    Given an object and a PluginTemplateContent method name, return all the registered content for the
+    object's model.
+    """
+    html = ''
+
+    plugin_template_classes = get_content_classes(obj._meta.label_lower)
+    for plugin_template_class in plugin_template_classes:
+        plugin_template_renderer = plugin_template_class(obj)
+        try:
+            content = getattr(plugin_template_renderer, method)()
+        except NotImplementedError:
+            # This content renderer class does not define content for this method
+            continue
+        html += content
+
+    return mark_safe(html)
+
+
 @register.simple_tag()
 @register.simple_tag()
 def plugin_buttons(obj):
 def plugin_buttons(obj):
     """
     """
     Fire signal to collect all buttons registered by plugins
     Fire signal to collect all buttons registered by plugins
     """
     """
-    html = ''
-    responses = register_detail_page_buttons.send(obj)
-    for receiver, response in responses:
-        if not isinstance(response, list):
-            response = [response]
-        for template in response:
-            if isinstance(template, str):
-                template_text = get_template(template).render({'obj': obj})
-                html += template_text
+    return _get_registered_content(obj, 'buttons')
 
 
-    return mark_safe(html)
 
 
+@register.simple_tag()
+def plugin_left_page(obj):
+    """
+    Fire signal to collect all left page content registered by plugins
+    """
+    return _get_registered_content(obj, 'left_page')
+
+
+@register.simple_tag()
+def plugin_right_page(obj):
+    """
+    Fire signal to collect all right page content registered by plugins
+    """
+    return _get_registered_content(obj, 'right_page')
+
+
+@register.simple_tag()
+def plugin_full_width_page(obj):
+    """
+    Fire signal to collect all full width page content registered by plugins
+    """
+    return _get_registered_content(obj, 'full_width_page')

+ 9 - 0
netbox/templates/circuits/circuit.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block title %}{{ circuit }}{% endblock %}
 {% block title %}{{ circuit }}{% endblock %}
 
 
@@ -28,6 +29,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons circuit %}
         {% if perms.circuits.add_circuit %}
         {% if perms.circuits.add_circuit %}
             {% clone_button circuit %}
             {% clone_button circuit %}
         {% endif %}
         {% endif %}
@@ -125,10 +127,17 @@
                 {% endif %}
                 {% endif %}
             </div>
             </div>
         </div>
         </div>
+        {% plugin_left_page circuit %}
 	</div>
 	</div>
 	<div class="col-md-6">
 	<div class="col-md-6">
         {% include 'circuits/inc/circuit_termination.html' with termination=termination_a side='A' %}
         {% include 'circuits/inc/circuit_termination.html' with termination=termination_a side='A' %}
         {% include 'circuits/inc/circuit_termination.html' with termination=termination_z side='Z' %}
         {% include 'circuits/inc/circuit_termination.html' with termination=termination_z side='Z' %}
+        {% plugin_right_page circuit %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page circuit %}
     </div>
     </div>
 </div>
 </div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/circuits/provider.html

@@ -3,6 +3,7 @@
 {% load static %}
 {% load static %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block title %}{{ provider }}{% endblock %}
 {% block title %}{{ provider }}{% endblock %}
 
 
@@ -28,6 +29,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons provider %}
         {% if show_graphs %}
         {% if show_graphs %}
             <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#graphs_modal" data-obj="{{ provider.name }}" data-url="{% url 'circuits-api:provider-graphs' pk=provider.pk %}" title="Show graphs">
             <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#graphs_modal" data-obj="{{ provider.name }}" data-url="{% url 'circuits-api:provider-graphs' pk=provider.pk %}" title="Show graphs">
                 <i class="fa fa-signal" aria-hidden="true"></i> Graphs
                 <i class="fa fa-signal" aria-hidden="true"></i> Graphs
@@ -116,6 +118,7 @@
                 {% endif %}
                 {% endif %}
             </div>
             </div>
         </div>
         </div>
+        {% plugin_left_page provider %}
 	</div>
 	</div>
 	<div class="col-md-8">
 	<div class="col-md-8">
         <div class="panel panel-default">
         <div class="panel panel-default">
@@ -132,9 +135,15 @@
             {% endif %}
             {% endif %}
         </div>
         </div>
     {% include 'inc/paginator.html' with paginator=circuits_table.paginator page=circuits_table.page %}
     {% include 'inc/paginator.html' with paginator=circuits_table.paginator page=circuits_table.page %}
+    {% plugin_right_page provider %}
     </div>
     </div>
 </div>
 </div>
 {% include 'inc/modal.html' with name='graphs' title='Graphs' %}
 {% include 'inc/modal.html' with name='graphs' title='Graphs' %}
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page provider %}
+    </div>
+</div>
 {% endblock %}
 {% endblock %}
 
 
 {% block javascript %}
 {% block javascript %}

+ 9 - 0
netbox/templates/dcim/cable.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -13,6 +14,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons cable %}
         {% if perms.dcim.change_cable %}
         {% if perms.dcim.change_cable %}
             {% edit_button cable %}
             {% edit_button cable %}
         {% endif %}
         {% endif %}
@@ -79,6 +81,7 @@
                     </tr>
                     </tr>
                 </table>
                 </table>
             </div>
             </div>
+            {% plugin_left_page cable %}
         </div>
         </div>
         <div class="col-md-6">
         <div class="col-md-6">
             <div class="panel panel-default">
             <div class="panel panel-default">
@@ -93,6 +96,12 @@
                 </div>
                 </div>
                 {% include 'dcim/inc/cable_termination.html' with termination=cable.termination_b %}
                 {% include 'dcim/inc/cable_termination.html' with termination=cable.termination_b %}
             </div>
             </div>
+            {% plugin_right_page cable %}
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-md-12">
+            {% plugin_full_width_page cable %}
         </div>
         </div>
     </div>
     </div>
 {% endblock %}
 {% endblock %}

+ 7 - 0
netbox/templates/dcim/device.html

@@ -333,6 +333,7 @@
                     {% endif %}
                     {% endif %}
                 </div>
                 </div>
             </div>
             </div>
+            {% plugin_left_page device %}
         </div>
         </div>
         <div class="col-md-6">
         <div class="col-md-6">
             {% if console_ports or power_ports %}
             {% if console_ports or power_ports %}
@@ -499,6 +500,12 @@
                     <div class="panel-body text-muted">None found</div>
                     <div class="panel-body text-muted">None found</div>
                 {% endif %}
                 {% endif %}
             </div>
             </div>
+            {% plugin_right_page device %}
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-md-12">
+            {% plugin_full_width_page device %}
         </div>
         </div>
     </div>
     </div>
     <div class="row">
     <div class="row">

+ 9 - 0
netbox/templates/dcim/devicetype.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block title %}{{ devicetype.manufacturer }} {{ devicetype.model }}{% endblock %}
 {% block title %}{{ devicetype.manufacturer }} {{ devicetype.model }}{% endblock %}
 
 
@@ -16,6 +17,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons devicetype %}
         {% if perms.dcim.change_devicetype %}
         {% if perms.dcim.change_devicetype %}
             <div class="btn-group">
             <div class="btn-group">
                 <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                 <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@@ -139,6 +141,7 @@
                 </tr>
                 </tr>
             </table>
             </table>
         </div>
         </div>
+        {% plugin_left_page devicetype %}
     </div>
     </div>
     <div class="col-md-6">
     <div class="col-md-6">
         {% include 'inc/custom_fields_panel.html' with obj=devicetype %}
         {% include 'inc/custom_fields_panel.html' with obj=devicetype %}
@@ -155,6 +158,7 @@
                 {% endif %}
                 {% endif %}
             </div>
             </div>
         </div>
         </div>
+        {% plugin_right_page devicetype %}
     </div>
     </div>
 </div>
 </div>
 {% if devicetype.consoleport_templates.exists or devicetype.powerport_templates.exists %}
 {% if devicetype.consoleport_templates.exists or devicetype.powerport_templates.exists %}
@@ -167,6 +171,11 @@
         </div>
         </div>
     </div>
     </div>
 {% endif %}
 {% endif %}
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page devicetype %}
+    </div>
+</div>
 {% if devicetype.is_parent_device or devicebay_table.rows %}
 {% if devicetype.is_parent_device or devicebay_table.rows %}
     <div class="row">
     <div class="row">
         <div class="col-md-12">
         <div class="col-md-12">

+ 9 - 0
netbox/templates/dcim/powerfeed.html

@@ -3,6 +3,7 @@
 {% load static %}
 {% load static %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -31,6 +32,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons powerfeed %}
         {% if perms.dcim.add_powerfeed %}
         {% if perms.dcim.add_powerfeed %}
             {% clone_button powerfeed %}
             {% clone_button powerfeed %}
         {% endif %}
         {% endif %}
@@ -123,6 +125,7 @@
         </div>
         </div>
         {% include 'inc/custom_fields_panel.html' with obj=powerfeed %}
         {% include 'inc/custom_fields_panel.html' with obj=powerfeed %}
         {% include 'extras/inc/tags_panel.html' with tags=powerfeed.tags.all url='dcim:powerfeed_list' %}
         {% include 'extras/inc/tags_panel.html' with tags=powerfeed.tags.all url='dcim:powerfeed_list' %}
+        {% plugin_left_page powerfeed %}
     </div>
     </div>
     <div class="col-md-6">
     <div class="col-md-6">
         <div class="panel panel-default">
         <div class="panel panel-default">
@@ -164,6 +167,12 @@
                 {% endif %}
                 {% endif %}
             </div>
             </div>
         </div>
         </div>
+        {% plugin_right_page powerfeed %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page powerfeed %}
     </div>
     </div>
 </div>
 </div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/dcim/powerpanel.html

@@ -3,6 +3,7 @@
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
 {% load static %}
 {% load static %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -30,6 +31,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons powerpanel %}
         {% if perms.dcim.change_powerpanel %}
         {% if perms.dcim.change_powerpanel %}
             {% edit_button powerpanel %}
             {% edit_button powerpanel %}
         {% endif %}
         {% endif %}
@@ -80,9 +82,16 @@
                 </tr>
                 </tr>
             </table>
             </table>
         </div>
         </div>
+        {% plugin_left_page powerpanel %}
     </div>
     </div>
 	<div class="col-md-9">
 	<div class="col-md-9">
         {% include 'panel_table.html' with table=powerfeed_table heading='Connected Feeds' %}
         {% include 'panel_table.html' with table=powerfeed_table heading='Connected Feeds' %}
+        {% plugin_right_page powerpanel %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page powerpanel %}
     </div>
     </div>
 </div>
 </div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/dcim/rack.html

@@ -3,6 +3,7 @@
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
 {% load static %}
 {% load static %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -27,6 +28,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons rack %}
         <a {% if prev_rack %}href="{% url 'dcim:rack' pk=prev_rack.pk %}"{% else %}disabled="disabled"{% endif %} class="btn btn-primary">
         <a {% if prev_rack %}href="{% url 'dcim:rack' pk=prev_rack.pk %}"{% else %}disabled="disabled"{% endif %} class="btn btn-primary">
             <span class="fa fa-chevron-left" aria-hidden="true"></span> Previous Rack
             <span class="fa fa-chevron-left" aria-hidden="true"></span> Previous Rack
         </a>
         </a>
@@ -312,6 +314,7 @@
                 </div>
                 </div>
             {% endif %}
             {% endif %}
         </div>
         </div>
+        {% plugin_left_page rack %}
 	</div>
 	</div>
     <div class="col-md-6">
     <div class="col-md-6">
         <div class="row" style="margin-bottom: 20px">
         <div class="row" style="margin-bottom: 20px">
@@ -369,6 +372,12 @@
                 </div>
                 </div>
             {% endif %}
             {% endif %}
         </div>
         </div>
+        {% plugin_right_page rack %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page rack %}
     </div>
     </div>
 </div>
 </div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/dcim/rackreservation.html

@@ -3,6 +3,7 @@
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
 {% load static %}
 {% load static %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -27,6 +28,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons rackreservation %}
         {% if perms.dcim.change_rackreservation %}
         {% if perms.dcim.change_rackreservation %}
             {% edit_button rackreservation %}
             {% edit_button rackreservation %}
         {% endif %}
         {% endif %}
@@ -119,6 +121,7 @@
                 </tr>
                 </tr>
             </table>
             </table>
         </div>
         </div>
+        {% plugin_left_page rackreservation %}
 	</div>
 	</div>
     <div class="col-md-6">
     <div class="col-md-6">
         {% with rack=rackreservation.rack %}
         {% with rack=rackreservation.rack %}
@@ -137,6 +140,12 @@
                 </div>
                 </div>
             </div>
             </div>
         {% endwith %}
         {% endwith %}
+        {% plugin_right_page rackreservation %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page rackreservation %}
     </div>
     </div>
 </div>
 </div>
 {% endblock %}
 {% endblock %}

+ 8 - 0
netbox/templates/dcim/site.html

@@ -5,6 +5,7 @@
 {% load plugins %}
 {% load plugins %}
 {% load static %}
 {% load static %}
 {% load tz %}
 {% load tz %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -214,6 +215,7 @@
                 {% endif %}
                 {% endif %}
             </div>
             </div>
         </div>
         </div>
+        {% plugin_left_page site %}
     </div>
     </div>
     <div class="col-md-5">
     <div class="col-md-5">
         <div class="panel panel-default">
         <div class="panel panel-default">
@@ -288,9 +290,15 @@
                 </div>
                 </div>
             {% endif %}
             {% endif %}
         </div>
         </div>
+        {% plugin_right_page site %}
 	</div>
 	</div>
 </div>
 </div>
 {% include 'inc/modal.html' with name='graphs' title='Graphs' %}
 {% include 'inc/modal.html' with name='graphs' title='Graphs' %}
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page site %}
+    </div>
+</div>
 {% endblock %}
 {% endblock %}
 
 
 {% block javascript %}
 {% block javascript %}

+ 9 - 0
netbox/templates/ipam/aggregate.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -26,6 +27,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons aggregate %}
         {% if perms.ipam.add_aggregate %}
         {% if perms.ipam.add_aggregate %}
             {% clone_button aggregate %}
             {% clone_button aggregate %}
         {% endif %}
         {% endif %}
@@ -88,10 +90,17 @@
                 </tr>
                 </tr>
             </table>
             </table>
         </div>
         </div>
+        {% plugin_left_page aggregate %}
     </div>
     </div>
     <div class="col-md-6">
     <div class="col-md-6">
         {% include 'inc/custom_fields_panel.html' with obj=aggregate %}
         {% include 'inc/custom_fields_panel.html' with obj=aggregate %}
         {% include 'extras/inc/tags_panel.html' with tags=aggregate.tags.all url='ipam:aggregate_list' %}
         {% include 'extras/inc/tags_panel.html' with tags=aggregate.tags.all url='ipam:aggregate_list' %}
+        {% plugin_right_page aggregate %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page aggregate %}
     </div>
     </div>
 </div>
 </div>
 <div class="row">
 <div class="row">

+ 9 - 0
netbox/templates/ipam/ipaddress.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -28,6 +29,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons ipaddress %}
         {% if perms.ipam.add_ipaddress %}
         {% if perms.ipam.add_ipaddress %}
             {% clone_button ipaddress %}
             {% clone_button ipaddress %}
         {% endif %}
         {% endif %}
@@ -152,6 +154,7 @@
         </div>
         </div>
         {% include 'inc/custom_fields_panel.html' with obj=ipaddress %}
         {% include 'inc/custom_fields_panel.html' with obj=ipaddress %}
         {% include 'extras/inc/tags_panel.html' with tags=ipaddress.tags.all url='ipam:ipaddress_list' %}
         {% include 'extras/inc/tags_panel.html' with tags=ipaddress.tags.all url='ipam:ipaddress_list' %}
+        {% plugin_left_page ipaddress %}
 	</div>
 	</div>
 	<div class="col-md-8">
 	<div class="col-md-8">
         {% include 'panel_table.html' with table=parent_prefixes_table heading='Parent Prefixes' %}
         {% include 'panel_table.html' with table=parent_prefixes_table heading='Parent Prefixes' %}
@@ -159,6 +162,12 @@
             {% include 'panel_table.html' with table=duplicate_ips_table heading='Duplicate IP Addresses' panel_class='danger' %}
             {% include 'panel_table.html' with table=duplicate_ips_table heading='Duplicate IP Addresses' panel_class='danger' %}
         {% endif %}
         {% endif %}
         {% include 'utilities/obj_table.html' with table=related_ips_table table_template='panel_table.html' heading='Related IP Addresses' panel_class='default noprint' %}
         {% include 'utilities/obj_table.html' with table=related_ips_table table_template='panel_table.html' heading='Related IP Addresses' panel_class='default noprint' %}
+        {% plugin_right_page ipaddress %}
 	</div>
 	</div>
 </div>
 </div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page ipaddress %}
+    </div>
+</div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/ipam/prefix.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -28,6 +29,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons prefix %}
         {% if perms.ipam.add_prefix and active_tab == 'prefixes' and first_available_prefix %}
         {% if perms.ipam.add_prefix and active_tab == 'prefixes' and first_available_prefix %}
             <a href="{% url 'ipam:prefix_add' %}?prefix={{ first_available_prefix }}&vrf={{ prefix.vrf.pk }}&site={{ prefix.site.pk }}&tenant_group={{ prefix.tenant.group.pk }}&tenant={{ prefix.tenant.pk }}" class="btn btn-success">
             <a href="{% url 'ipam:prefix_add' %}?prefix={{ first_available_prefix }}&vrf={{ prefix.vrf.pk }}&site={{ prefix.site.pk }}&tenant_group={{ prefix.tenant.group.pk }}&tenant={{ prefix.tenant.pk }}" class="btn btn-success">
                 <i class="fa fa-plus" aria-hidden="true"></i> Add Child Prefix
                 <i class="fa fa-plus" aria-hidden="true"></i> Add Child Prefix
@@ -187,12 +189,19 @@
             </div>
             </div>
             {% include 'inc/custom_fields_panel.html' with obj=prefix %}
             {% include 'inc/custom_fields_panel.html' with obj=prefix %}
             {% include 'extras/inc/tags_panel.html' with tags=prefix.tags.all url='ipam:prefix_list' %}
             {% include 'extras/inc/tags_panel.html' with tags=prefix.tags.all url='ipam:prefix_list' %}
+            {% plugin_left_page prefix %}
         </div>
         </div>
         <div class="col-md-7">
         <div class="col-md-7">
             {% if duplicate_prefix_table.rows %}
             {% if duplicate_prefix_table.rows %}
                 {% include 'panel_table.html' with table=duplicate_prefix_table heading='Duplicate Prefixes' panel_class='danger' %}
                 {% include 'panel_table.html' with table=duplicate_prefix_table heading='Duplicate Prefixes' panel_class='danger' %}
             {% endif %}
             {% endif %}
             {% include 'panel_table.html' with table=parent_prefix_table heading='Parent Prefixes' panel_class='default' %}
             {% include 'panel_table.html' with table=parent_prefix_table heading='Parent Prefixes' panel_class='default' %}
+            {% plugin_right_page prefix %}
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-md-12">
+            {% plugin_full_width_page prefix %}
         </div>
         </div>
     </div>
     </div>
 {% endblock %}
 {% endblock %}

+ 12 - 1
netbox/templates/ipam/service.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block content %}
 {% block content %}
 <div class="row noprint">
 <div class="row noprint">
@@ -26,6 +27,7 @@
     </div>
     </div>
 </div>
 </div>
 <div class="pull-right">
 <div class="pull-right">
+    {% plugin_buttons service %}
     {% if perms.dcim.change_service %}
     {% if perms.dcim.change_service %}
         {% edit_button service %}
         {% edit_button service %}
     {% endif %}
     {% endif %}
@@ -81,6 +83,15 @@
         </div>
         </div>
         {% include 'inc/custom_fields_panel.html' with obj=service %}
         {% include 'inc/custom_fields_panel.html' with obj=service %}
         {% include 'extras/inc/tags_panel.html' with tags=service.tags.all url='ipam:service_list' %}
         {% include 'extras/inc/tags_panel.html' with tags=service.tags.all url='ipam:service_list' %}
-	</div>
+        {% plugin_left_page service %}
+    </div>
+    <div class="col-md-6">
+        {% plugin_right_page service %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page service %}
+    </div>
 </div>
 </div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/ipam/vlan.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -31,6 +32,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons vlan %}
         {% if perms.ipam.add_vlan %}
         {% if perms.ipam.add_vlan %}
             {% clone_button vlan %}
             {% clone_button vlan %}
         {% endif %}
         {% endif %}
@@ -139,6 +141,7 @@
             </div>
             </div>
             {% include 'inc/custom_fields_panel.html' with obj=vlan %}
             {% include 'inc/custom_fields_panel.html' with obj=vlan %}
             {% include 'extras/inc/tags_panel.html' with tags=vlan.tags.all url='ipam:vlan_list' %}
             {% include 'extras/inc/tags_panel.html' with tags=vlan.tags.all url='ipam:vlan_list' %}
+            {% plugin_left_page vlan %}
         </div>
         </div>
         <div class="col-md-8">
         <div class="col-md-8">
             <div class="panel panel-default">
             <div class="panel panel-default">
@@ -155,6 +158,12 @@
                     </div>
                     </div>
                 {% endif %}
                 {% endif %}
             </div>
             </div>
+            {% plugin_right_page vlan %}
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-md-12">
+            {% plugin_full_width_page vlan %}
         </div>
         </div>
     </div>
     </div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/ipam/vrf.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -25,6 +26,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons vrf %}
         {% if perms.ipam.add_vrf %}
         {% if perms.ipam.add_vrf %}
             {% clone_button vrf %}
             {% clone_button vrf %}
         {% endif %}
         {% endif %}
@@ -97,9 +99,16 @@
 		    </table>
 		    </table>
         </div>
         </div>
         {% include 'extras/inc/tags_panel.html' with tags=vrf.tags.all url='ipam:vrf_list' %}
         {% include 'extras/inc/tags_panel.html' with tags=vrf.tags.all url='ipam:vrf_list' %}
+        {% plugin_left_page vrf %}
 	</div>
 	</div>
 	<div class="col-md-6">
 	<div class="col-md-6">
         {% include 'inc/custom_fields_panel.html' with obj=vrf %}
         {% include 'inc/custom_fields_panel.html' with obj=vrf %}
+        {% plugin_right_page vrf %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page vrf %}
     </div>
     </div>
 </div>
 </div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/secrets/secret.html

@@ -4,6 +4,7 @@
 {% load helpers %}
 {% load helpers %}
 {% load secret_helpers %}
 {% load secret_helpers %}
 {% load static %}
 {% load static %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -16,6 +17,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons secret %}
         {% if perms.secrets.change_secret %}
         {% if perms.secrets.change_secret %}
             {% edit_button secret %}
             {% edit_button secret %}
         {% endif %}
         {% endif %}
@@ -65,6 +67,7 @@
             </table>
             </table>
         </div>
         </div>
         {% include 'inc/custom_fields_panel.html' with obj=secret %}
         {% include 'inc/custom_fields_panel.html' with obj=secret %}
+        {% plugin_left_page secret %}
 	</div>
 	</div>
 	<div class="col-md-6">
 	<div class="col-md-6">
         {% if secret|decryptable_by:request.user %}
         {% if secret|decryptable_by:request.user %}
@@ -100,6 +103,12 @@
             </div>
             </div>
         {% endif %}
         {% endif %}
         {% include 'extras/inc/tags_panel.html' with tags=secret.tags.all url='secrets:secret_list' %}
         {% include 'extras/inc/tags_panel.html' with tags=secret.tags.all url='secrets:secret_list' %}
+        {% plugin_right_page secret %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page secret %}
     </div>
     </div>
 </div>
 </div>
 
 

+ 9 - 0
netbox/templates/tenancy/tenant.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -28,6 +29,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons tenant %}
         {% if perms.tenancy.add_tenant %}
         {% if perms.tenancy.add_tenant %}
             {% clone_button tenant %}
             {% clone_button tenant %}
         {% endif %}
         {% endif %}
@@ -93,6 +95,7 @@
                 {% endif %}
                 {% endif %}
             </div>
             </div>
         </div>
         </div>
+        {% plugin_left_page tenant %}
 	</div>
 	</div>
 	<div class="col-md-5">
 	<div class="col-md-5">
         <div class="panel panel-default">
         <div class="panel panel-default">
@@ -146,6 +149,12 @@
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
+        {% plugin_right_page tenant %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page tenant %}
     </div>
     </div>
 </div>
 </div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/virtualization/cluster.html

@@ -2,6 +2,7 @@
 {% load buttons %}
 {% load buttons %}
 {% load custom_links %}
 {% load custom_links %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint" xmlns="http://www.w3.org/1999/html">
     <div class="row noprint" xmlns="http://www.w3.org/1999/html">
@@ -28,6 +29,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons cluster %}
         {% if perms.virtualization.add_cluster %}
         {% if perms.virtualization.add_cluster %}
             {% clone_button cluster %}
             {% clone_button cluster %}
         {% endif %}
         {% endif %}
@@ -121,6 +123,7 @@
                 {% endif %}
                 {% endif %}
             </div>
             </div>
         </div>
         </div>
+        {% plugin_left_page cluster %}
     </div>
     </div>
     <div class="col-md-7">
     <div class="col-md-7">
         <div class="panel panel-default">
         <div class="panel panel-default">
@@ -148,6 +151,12 @@
                 </form>
                 </form>
             {% endif %}
             {% endif %}
         </div>
         </div>
+        {% plugin_right_page cluster %}
 	</div>
 	</div>
 </div>
 </div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page cluster %}
+    </div>
+</div>
 {% endblock %}
 {% endblock %}

+ 9 - 0
netbox/templates/virtualization/virtualmachine.html

@@ -3,6 +3,7 @@
 {% load custom_links %}
 {% load custom_links %}
 {% load static %}
 {% load static %}
 {% load helpers %}
 {% load helpers %}
+{% load plugins %}
 
 
 {% block header %}
 {% block header %}
     <div class="row noprint">
     <div class="row noprint">
@@ -28,6 +29,7 @@
         </div>
         </div>
     </div>
     </div>
     <div class="pull-right noprint">
     <div class="pull-right noprint">
+        {% plugin_buttons virtualmachine %}
         {% if perms.virtualization.add_virtualmachine %}
         {% if perms.virtualization.add_virtualmachine %}
             {% clone_button virtualmachine %}
             {% clone_button virtualmachine %}
         {% endif %}
         {% endif %}
@@ -158,6 +160,7 @@
                 {% endif %}
                 {% endif %}
             </div>
             </div>
         </div>
         </div>
+        {% plugin_left_page virtualmachine %}
     </div>
     </div>
 	<div class="col-md-6">
 	<div class="col-md-6">
         <div class="panel panel-default">
         <div class="panel panel-default">
@@ -235,6 +238,12 @@
                 </div>
                 </div>
             {% endif %}
             {% endif %}
         </div>
         </div>
+        {% plugin_right_page virtualmachine %}
+    </div>
+</div>
+<div class="row">
+    <div class="col-md-12">
+        {% plugin_full_width_page virtualmachine %}
     </div>
     </div>
 </div>
 </div>
 <div class="row">
 <div class="row">