Browse Source

Added front-end UI for RackGroups

Jeremy Stretch 9 years ago
parent
commit
2f86d5e43d

+ 18 - 0
netbox/dcim/forms.py

@@ -69,6 +69,24 @@ class SiteImportForm(BulkImportForm, BootstrapMixin):
 
 
 #
+# Rack groups
+#
+
+class RackGroupBulkDeleteForm(ConfirmationForm):
+    pk = forms.ModelMultipleChoiceField(queryset=RackGroup.objects.all(), widget=forms.MultipleHiddenInput)
+
+
+def rackgroup_site_choices():
+    site_choices = Site.objects.annotate(rack_count=Count('racks'))
+    return [(s.slug, '{} ({})'.format(s.name, s.rack_count)) for s in site_choices]
+
+
+class RackGroupFilterForm(forms.Form, BootstrapMixin):
+    site = forms.MultipleChoiceField(required=False, choices=rackgroup_site_choices,
+                                     widget=forms.SelectMultiple(attrs={'size': 8}))
+
+
+#
 # Racks
 #
 

+ 3 - 0
netbox/dcim/models.py

@@ -142,6 +142,9 @@ class RackGroup(models.Model):
     def __unicode__(self):
         return self.name
 
+    def get_absolute_url(self):
+        return "{}?group={}".format(reverse('dcim:rack_list'), self.slug)
+
 
 class Rack(models.Model):
     """

+ 33 - 16
netbox/dcim/tables.py

@@ -1,27 +1,17 @@
 import django_tables2 as tables
 from django_tables2.utils import Accessor
 
-from .models import Site, Rack, DeviceType, ConsolePortTemplate, ConsoleServerPortTemplate, PowerPortTemplate, \
-    PowerOutletTemplate, InterfaceTemplate, Device, ConsolePort, PowerPort
-
-
-PREFIXES_PER_VLAN = """
-{% for p in record.prefix_set.all %}
-    <a href="{% url 'ipam:prefix' pk=p.pk %}">{{ p }}</a>
-    {% if not forloop.last %}<br />{% endif %}
-{% endfor %}
-"""
-
-STATUS_LABEL = """
-<span class="label label-{{ record.status.get_bootstrap_class_display|lower }}">
-    {{ record.status.name }}
-</span>
-"""
+from .models import Site, RackGroup, Rack, DeviceType, ConsolePortTemplate, ConsoleServerPortTemplate, \
+    PowerPortTemplate, PowerOutletTemplate, InterfaceTemplate, Device, ConsolePort, PowerPort
 
 DEVICE_LINK = """
 <a href="{% url 'dcim:device' pk=record.pk %}">{{ record.name|default:'<span class="label label-info">Unnamed device</span>' }}</a>
 """
 
+RACKGROUP_EDIT_LINK = """
+<a href="{% url 'dcim:rackgroup_edit' pk=record.pk %}">Edit</a>
+"""
+
 
 #
 # Sites
@@ -47,6 +37,33 @@ class SiteTable(tables.Table):
 
 
 #
+# Rack groups
+#
+
+class RackGroupTable(tables.Table):
+    name = tables.LinkColumn(verbose_name='Name')
+    site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
+    slug = tables.Column(verbose_name='Slug')
+
+    class Meta:
+        model = RackGroup
+        fields = ('name', 'site', 'slug')
+        empty_text = "No rack groups were found."
+        attrs = {
+            'class': 'table table-hover',
+        }
+
+
+class RackGroupBulkEditTable(RackGroupTable):
+    pk = tables.CheckBoxColumn()
+    edit = tables.TemplateColumn(template_code=RACKGROUP_EDIT_LINK, verbose_name='')
+
+    class Meta(RackGroupTable.Meta):
+        model = None  # django_tables2 bugfix
+        fields = ('pk', 'name', 'site', 'slug', 'edit')
+
+
+#
 # Racks
 #
 

+ 6 - 0
netbox/dcim/urls.py

@@ -17,6 +17,12 @@ urlpatterns = [
     url(r'^sites/(?P<slug>[\w-]+)/edit/$', views.site_edit, name='site_edit'),
     url(r'^sites/(?P<slug>[\w-]+)/delete/$', views.site_delete, name='site_delete'),
 
+    # Rack groups
+    url(r'^rack-groups/$', views.RackGroupListView.as_view(), name='rackgroup_list'),
+    url(r'^rack-groups/add/$', views.RackGroupAddView.as_view(), name='rackgroup_add'),
+    url(r'^rack-groups/delete/$', views.RackGroupBulkDeleteView.as_view(), name='rackgroup_bulk_delete'),
+    url(r'^rack-groups/(?P<pk>\d+)/edit/$', views.RackGroupEditView.as_view(), name='rackgroup_edit'),
+
     # Racks
     url(r'^racks/$', views.RackListView.as_view(), name='rack_list'),
     url(r'^racks/add/$', views.rack_add, name='rack_add'),

+ 59 - 20
netbox/dcim/views.py

@@ -11,6 +11,7 @@ from django.http import HttpResponseRedirect
 from django.shortcuts import get_object_or_404, redirect, render
 from django.utils.http import urlencode
 from django.views.generic import View
+from django.views.generic.edit import CreateView, UpdateView
 
 from ipam.models import Prefix, IPAddress, VLAN
 from circuits.models import Circuit
@@ -18,26 +19,28 @@ from utilities.error_handlers import handle_protectederror
 from utilities.forms import ConfirmationForm
 from utilities.views import ObjectListView, BulkImportView, BulkEditView, BulkDeleteView
 
-from .filters import RackFilter, DeviceTypeFilter, DeviceFilter, ConsoleConnectionFilter, PowerConnectionFilter, \
-    InterfaceConnectionFilter
-from .forms import SiteForm, SiteImportForm, RackForm, RackImportForm, RackBulkEditForm, RackBulkDeleteForm, \
-    RackFilterForm, DeviceTypeForm, DeviceTypeBulkEditForm, DeviceTypeBulkDeleteForm, DeviceTypeFilterForm, \
-    DeviceForm, DeviceImportForm, DeviceBulkEditForm, DeviceBulkDeleteForm, DeviceFilterForm, \
-    ConsolePortForm, ConsolePortCreateForm, ConsolePortConnectionForm, ConsoleConnectionImportForm, \
-    ConsoleServerPortForm, ConsoleServerPortCreateForm, ConsoleServerPortConnectionForm, PowerPortForm, \
-    PowerPortCreateForm, PowerPortConnectionForm, PowerConnectionImportForm, PowerOutletForm, PowerOutletCreateForm, \
-    PowerOutletConnectionForm, InterfaceForm, InterfaceCreateForm, InterfaceBulkCreateForm, InterfaceConnectionForm, \
-    InterfaceConnectionDeletionForm, InterfaceConnectionImportForm, ConsoleConnectionFilterForm, \
-    PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm, ConsolePortTemplateForm, \
-    ConsoleServerPortTemplateForm, PowerPortTemplateForm, PowerOutletTemplateForm, InterfaceTemplateForm
-from .models import Site, Rack, DeviceType, ConsolePortTemplate, ConsoleServerPortTemplate, PowerPortTemplate, \
-    PowerOutletTemplate, InterfaceTemplate, Device, ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, \
-    InterfaceConnection, Module, CONNECTION_STATUS_CONNECTED
-from .tables import SiteTable, RackTable, RackBulkEditTable, DeviceTypeTable, DeviceTypeBulkEditTable, DeviceTable, \
-    DeviceBulkEditTable, DeviceImportTable, ConsoleConnectionTable, PowerConnectionTable, InterfaceConnectionTable, \
-    ConsolePortTemplateTable, ConsoleServerPortTemplateTable, PowerPortTemplateTable, PowerOutletTemplateTable, \
-    InterfaceTemplateTable, ConsolePortTemplateBulkDeleteTable, ConsoleServerPortTemplateBulkDeleteTable, \
-    PowerPortTemplateBulkDeleteTable, PowerOutletTemplateBulkDeleteTable, InterfaceTemplateBulkDeleteTable
+from .filters import RackGroupFilter, RackFilter, DeviceTypeFilter, DeviceFilter, ConsoleConnectionFilter, \
+    PowerConnectionFilter, InterfaceConnectionFilter
+from .forms import SiteForm, SiteImportForm, RackGroupFilterForm, RackGroupBulkDeleteForm, RackForm, RackImportForm, \
+    RackBulkEditForm, RackBulkDeleteForm, RackFilterForm, DeviceTypeForm, DeviceTypeBulkEditForm, \
+    DeviceTypeBulkDeleteForm, DeviceTypeFilterForm, DeviceForm, DeviceImportForm, DeviceBulkEditForm, \
+    DeviceBulkDeleteForm, DeviceFilterForm, ConsolePortForm, ConsolePortCreateForm, ConsolePortConnectionForm, \
+    ConsoleConnectionImportForm, ConsoleServerPortForm, ConsoleServerPortCreateForm, ConsoleServerPortConnectionForm, \
+    PowerPortForm, PowerPortCreateForm, PowerPortConnectionForm, PowerConnectionImportForm, PowerOutletForm, \
+    PowerOutletCreateForm, PowerOutletConnectionForm, InterfaceForm, InterfaceCreateForm, InterfaceBulkCreateForm, \
+    InterfaceConnectionForm, InterfaceConnectionDeletionForm, InterfaceConnectionImportForm, \
+    ConsoleConnectionFilterForm, PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm, \
+    ConsolePortTemplateForm, ConsoleServerPortTemplateForm, PowerPortTemplateForm, PowerOutletTemplateForm, \
+    InterfaceTemplateForm
+from .models import Site, RackGroup, Rack, DeviceType, ConsolePortTemplate, ConsoleServerPortTemplate, \
+    PowerPortTemplate, PowerOutletTemplate, InterfaceTemplate, Device, ConsolePort, ConsoleServerPort, PowerPort, \
+    PowerOutlet, Interface, InterfaceConnection, Module, CONNECTION_STATUS_CONNECTED
+from .tables import SiteTable, RackGroupTable, RackGroupBulkEditTable, RackTable, RackBulkEditTable, DeviceTypeTable, \
+    DeviceTypeBulkEditTable, DeviceTable, DeviceBulkEditTable, DeviceImportTable, ConsoleConnectionTable, \
+    PowerConnectionTable, InterfaceConnectionTable, ConsolePortTemplateTable, ConsoleServerPortTemplateTable, \
+    PowerPortTemplateTable, PowerOutletTemplateTable, InterfaceTemplateTable, ConsolePortTemplateBulkDeleteTable, \
+    ConsoleServerPortTemplateBulkDeleteTable, PowerPortTemplateBulkDeleteTable, PowerOutletTemplateBulkDeleteTable, \
+    InterfaceTemplateBulkDeleteTable
 
 
 EXPANSION_PATTERN = '\[(\d+-\d+)\]'
@@ -172,6 +175,42 @@ class SiteBulkImportView(PermissionRequiredMixin, BulkImportView):
 
 
 #
+# Rack groups
+#
+
+class RackGroupListView(ObjectListView):
+    queryset = RackGroup.objects.all()
+    filter = RackGroupFilter
+    filter_form = RackGroupFilterForm
+    table = RackGroupTable
+    edit_table = RackGroupBulkEditTable
+    edit_table_permissions = ['dcim.change_rackgroup', 'dcim.delete_rackgroup']
+    template_name = 'dcim/rackgroup_list.html'
+
+
+class RackGroupAddView(PermissionRequiredMixin, CreateView):
+    permission_required = 'dcim.add_rackgroup'
+    model = RackGroup
+    fields = ['site', 'name', 'slug']
+    template_name = 'dcim/rackgroup_edit.html'
+
+
+class RackGroupEditView(PermissionRequiredMixin, UpdateView):
+    permission_required = 'dcim.change_rackgroup'
+    model = RackGroup
+    fields = ['site', 'name', 'slug']
+    template_name = 'dcim/rackgroup_edit.html'
+
+
+class RackGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
+    permission_required = 'dcim.delete_rackgroup'
+    cls = RackGroup
+    form = RackGroupBulkDeleteForm
+    template_name = 'dcim/rackgroup_bulk_delete.html'
+    redirect_url = 'dcim:rackgroup_list'
+
+
+#
 # Racks
 #
 

+ 45 - 40
netbox/templates/_base.html

@@ -27,53 +27,58 @@
                             <a href="{% url 'dcim:site_list' %}">Sites</a>
                         {% endif %}
                     </li>
-                    <li class="dropdown{% if '/racks/' in request.path %} active{% endif %}">
-                        {% if perms.dcim.add_rack %}
+                    <li class="dropdown{% if '/racks/' in request.path or '/rack-groups/' in request.path %} active{% endif %}">
                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Racks <span class="caret"></span></a>
                         <ul class="dropdown-menu">
                             <li><a href="{% url 'dcim:rack_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Racks</a></li>
-                            <li><a href="{% url 'dcim:rack_add' %}"><i class="glyphicon glyphicon-plus" aria-hidden="true"></i> Add a Rack</a></li>
-                            <li><a href="{% url 'dcim:rack_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Racks</a></li>
+                            {% if perms.dcim.add_rack %}
+                                <li><a href="{% url 'dcim:rack_add' %}"><i class="glyphicon glyphicon-plus" aria-hidden="true"></i> Add a Rack</a></li>
+                                <li><a href="{% url 'dcim:rack_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Racks</a></li>
+                            {% endif %}
+                            {% if perms.dcim.add_rack or perms.dcim.add_rackgroup %}
+                                <li class="divider"></li>
+                            {% endif %}
+                            <li><a href="{% url 'dcim:rackgroup_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Rack Groups</a></li>
+                            {% if perms.dcim.add_rackgroup %}
+                                <li><a href="{% url 'dcim:rackgroup_add' %}"><i class="glyphicon glyphicon-plus" aria-hidden="true"></i> Add a Rack Group</a></li>
+                            {% endif %}
                         </ul>
-                        {% else %}
-                            <a href="{% url 'dcim:rack_list' %}">Racks</a>
-                        {% endif %}
                     </li>
                     <li class="dropdown{% if '/devices/' in request.path or '/device-types/' in request.path or '-connections/' in request.path %} active{% endif %}">
-                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Devices <span class="caret"></span></a>
-                            <ul class="dropdown-menu">
-                                <li><a href="{% url 'dcim:device_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Devices</a></li>
-                                {% if perms.dcim.add_device %}
-                                    <li><a href="{% url 'dcim:device_add' %}"><i class="glyphicon glyphicon-plus" aria-hidden="true"></i> Add a Device</a></li>
-                                    <li><a href="{% url 'dcim:device_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Devices</a></li>
-                                {% endif %}
-                                {% if perms.ipam.add_device or perms.ipam.add_devicetype %}
-                                    <li class="divider"></li>
-                                {% endif %}
-                                <li><a href="{% url 'dcim:devicetype_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Device Types</a></li>
-                                {% if perms.dcim.add_device %}
-                                    <li><a href="{% url 'dcim:devicetype_add' %}"><i class="glyphicon glyphicon-plus" aria-hidden="true"></i> Add a Device Type</a></li>
-                                {% endif %}
+                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Devices <span class="caret"></span></a>
+                        <ul class="dropdown-menu">
+                            <li><a href="{% url 'dcim:device_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Devices</a></li>
+                            {% if perms.dcim.add_device %}
+                                <li><a href="{% url 'dcim:device_add' %}"><i class="glyphicon glyphicon-plus" aria-hidden="true"></i> Add a Device</a></li>
+                                <li><a href="{% url 'dcim:device_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Devices</a></li>
+                            {% endif %}
+                            {% if perms.ipam.add_device or perms.ipam.add_devicetype %}
                                 <li class="divider"></li>
-                                <li><a href="{% url 'dcim:console_connections_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Console Connections</a></li>
-                                {% if perms.dcim.change_consoleport %}
-                                    <li><a href="{% url 'dcim:console_connections_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Console Connections</a></li>
-                                {% endif %}
-                                {% if perms.ipam.change_consoleport or perms.ipam.change_powerport %}
-                                    <li class="divider"></li>
-                                {% endif %}
-                                <li><a href="{% url 'dcim:power_connections_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Power Connections</a></li>
-                                {% if perms.dcim.change_powerport %}
-                                    <li><a href="{% url 'dcim:power_connections_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Power Connections</a></li>
-                                {% endif %}
-                                {% if perms.ipam.change_powerport or perms.ipam.add_interfaceconnection %}
-                                    <li class="divider"></li>
-                                {% endif %}
-                                <li><a href="{% url 'dcim:interface_connections_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Interface Connections</a></li>
-                                {% if perms.dcim.add_interfaceconnection %}
-                                    <li><a href="{% url 'dcim:interface_connections_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Interface Connections</a></li>
-                                {% endif %}
-                            </ul>
+                            {% endif %}
+                            <li><a href="{% url 'dcim:devicetype_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Device Types</a></li>
+                            {% if perms.dcim.add_device %}
+                                <li><a href="{% url 'dcim:devicetype_add' %}"><i class="glyphicon glyphicon-plus" aria-hidden="true"></i> Add a Device Type</a></li>
+                            {% endif %}
+                            <li class="divider"></li>
+                            <li><a href="{% url 'dcim:console_connections_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Console Connections</a></li>
+                            {% if perms.dcim.change_consoleport %}
+                                <li><a href="{% url 'dcim:console_connections_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Console Connections</a></li>
+                            {% endif %}
+                            {% if perms.ipam.change_consoleport or perms.ipam.change_powerport %}
+                                <li class="divider"></li>
+                            {% endif %}
+                            <li><a href="{% url 'dcim:power_connections_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Power Connections</a></li>
+                            {% if perms.dcim.change_powerport %}
+                                <li><a href="{% url 'dcim:power_connections_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Power Connections</a></li>
+                            {% endif %}
+                            {% if perms.ipam.change_powerport or perms.ipam.add_interfaceconnection %}
+                                <li class="divider"></li>
+                            {% endif %}
+                            <li><a href="{% url 'dcim:interface_connections_list' %}"><i class="glyphicon glyphicon-search" aria-hidden="true"></i> Interface Connections</a></li>
+                            {% if perms.dcim.add_interfaceconnection %}
+                                <li><a href="{% url 'dcim:interface_connections_import' %}"><i class="glyphicon glyphicon-import" aria-hidden="true"></i> Import Interface Connections</a></li>
+                            {% endif %}
+                        </ul>
                     </li>
                     <li class="dropdown{% if '/ip-addresses/' in request.path or '/prefixes/' in request.path or '/aggregates/' in request.path %} active{% endif %}">
                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">IP Space <span class="caret"></span></a>

+ 13 - 0
netbox/templates/dcim/inc/rackgroup_table.html

@@ -0,0 +1,13 @@
+{% load render_table from django_tables2 %}
+{% if perms.dcim.delete_rackgroup %}
+    <form method="post" class="form form-horizontal">
+        {% csrf_token %}
+        {% render_table table table_template|default:'table.html' %}
+        <button type="submit" name="_delete" formaction="{% url 'dcim:rackgroup_bulk_delete' %}" class="btn btn-danger btn-sm">
+            <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
+            Delete Selected
+        </button>
+    </form>
+{% else %}
+    {% render_table table table_template|default:'table.html' %}
+{% endif %}

+ 15 - 0
netbox/templates/dcim/rackgroup_bulk_delete.html

@@ -0,0 +1,15 @@
+{% extends 'utilities/confirmation_form.html' %}
+{% load form_helpers %}
+
+{% block title %}Delete Rack Groups?{% endblock %}
+
+{% block message %}
+    <p>
+        Are you sure you want to delete these rack groups?
+    </p>
+    <ul>
+        {% for rg in selected_objects %}
+            <li>{{ rg }} ({{ rg.site }})</li>
+        {% endfor %}
+    </ul>
+{% endblock %}

+ 49 - 0
netbox/templates/dcim/rackgroup_edit.html

@@ -0,0 +1,49 @@
+{% extends '_base.html' %}
+{% load form_helpers %}
+
+{% block title %}{% if rack %}Editing rack group {{ rackgroup }}{% else %}Add a rack group{% endif %}{% endblock %}
+
+{% block content %}
+<form action="." method="post" class="form form-horizontal">
+    {% csrf_token %}
+    <div class="row">
+        <div class="col-md-6 col-md-offset-3">
+            {% if rackgroup %}
+                <h1>Rack group {{ rackgroup }}</h1>
+            {% else %}
+                <h1>Add a Rack Group</h1>
+            {% endif %}
+            {% if form.non_field_errors %}
+                <div class="panel panel-danger">
+                    <div class="panel-heading"><strong>Errors</strong></div>
+                    <div class="panel-body">
+                        {{ form.non_field_errors }}
+                    </div>
+                </div>
+            {% endif %}
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-md-6 col-md-offset-3">
+            <div class="panel panel-default">
+                <div class="panel-heading"><strong>Rack Group</strong></div>
+                <div class="panel-body">
+                    {% render_form form %}
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-md-6 col-md-offset-3 text-right">
+            {% if rackgroup %}
+                <button type="submit" name="_update" class="btn btn-primary">Update</button>
+                <a href="{% url 'dcim:rackgroup_list' %}" class="btn btn-default">Cancel</a>
+            {% else %}
+                <button type="submit" name="_create" class="btn btn-primary">Create</button>
+                <button type="submit" name="_addanother" class="btn btn-primary">Create and Add Another</button>
+                <a href="{% url 'dcim:rackgroup_list' %}" class="btn btn-default">Cancel</a>
+            {% endif %}
+        </div>
+    </div>
+</form>
+{% endblock %}

+ 24 - 0
netbox/templates/dcim/rackgroup_list.html

@@ -0,0 +1,24 @@
+{% extends '_base.html' %}
+{% load helpers %}
+
+{% block title %}Rack Groups{% endblock %}
+
+{% block content %}
+<div class="pull-right">
+    {% if perms.dcim.add_rackgroup %}
+        <a href="{% url 'dcim:rackgroup_add' %}" class="btn btn-primary">
+            <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
+            Add a rack group
+        </a>
+    {% endif %}
+</div>
+<h1>Rack Groups</h1>
+<div class="row">
+	<div class="col-md-9">
+        {% include 'dcim/inc/rackgroup_table.html' %}
+    </div>
+    <div class="col-md-3">
+		{% include 'inc/filter_panel.html' %}
+    </div>
+</div>
+{% endblock %}