From 13cc29cd8cb4f92ce2fb81d4b74c3001d4d0bcb3 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 20 Apr 2017 13:07:22 -0400 Subject: [PATCH] Closes #951: Provide a side-by-side view of rack elevations --- netbox/dcim/forms.py | 9 ++-- netbox/dcim/urls.py | 1 + netbox/dcim/views.py | 42 ++++++++++++++++ netbox/templates/_base.html | 1 + .../templates/dcim/rack_elevation_list.html | 50 +++++++++++++++++++ netbox/templates/ipam/prefix_list.html | 13 ++--- netbox/templates/paginator.html | 27 ++++------ netbox/templates/panel_table.html | 2 +- netbox/templates/table.html | 2 +- netbox/templates/table_paginator.html | 34 +++++++++++++ netbox/utilities/templatetags/helpers.py | 29 +++-------- 11 files changed, 156 insertions(+), 54 deletions(-) create mode 100644 netbox/templates/dcim/rack_elevation_list.html create mode 100644 netbox/templates/table_paginator.html diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index f3a353f5a..f48e5aa80 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -1,6 +1,5 @@ -import re - from mptt.forms import TreeNodeChoiceField +import re from django import forms from django.contrib.postgres.forms.array import SimpleArrayField @@ -21,9 +20,9 @@ from .models import ( DeviceBay, DeviceBayTemplate, CONNECTION_STATUS_CHOICES, CONNECTION_STATUS_PLANNED, CONNECTION_STATUS_CONNECTED, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceRole, DeviceType, Interface, IFACE_FF_CHOICES, IFACE_FF_LAG, IFACE_ORDERING_CHOICES, InterfaceConnection, InterfaceTemplate, - Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, RACK_TYPE_CHOICES, - RACK_WIDTH_CHOICES, Rack, RackGroup, RackReservation, RackRole, Region, Site, STATUS_CHOICES, SUBDEVICE_ROLE_CHILD, - SUBDEVICE_ROLE_PARENT, VIRTUAL_IFACE_TYPES + Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, + RACK_TYPE_CHOICES, RACK_WIDTH_CHOICES, Rack, RackGroup, RackReservation, RackRole, Region, Site, STATUS_CHOICES, + SUBDEVICE_ROLE_CHILD, SUBDEVICE_ROLE_PARENT, VIRTUAL_IFACE_TYPES, ) diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index 023d4e87d..8e666f406 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -47,6 +47,7 @@ urlpatterns = [ # Racks url(r'^racks/$', views.RackListView.as_view(), name='rack_list'), + url(r'^rack-elevations/$', views.RackElevationListView.as_view(), name='rack_elevation_list'), url(r'^racks/add/$', views.RackEditView.as_view(), name='rack_add'), url(r'^racks/import/$', views.RackBulkImportView.as_view(), name='rack_import'), url(r'^racks/edit/$', views.RackBulkEditView.as_view(), name='rack_bulk_edit'), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 9500b1914..5eb80005d 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -6,6 +6,7 @@ from operator import attrgetter from django.contrib import messages from django.contrib.auth.decorators import permission_required from django.contrib.auth.mixins import PermissionRequiredMixin +from django.core.paginator import EmptyPage, PageNotAnInteger from django.db.models import Count from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect, render @@ -17,6 +18,7 @@ from ipam.models import Prefix, Service, VLAN from circuits.models import Circuit from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE from utilities.forms import ConfirmationForm +from utilities.paginator import EnhancedPaginator from utilities.views import ( BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView, ) @@ -291,6 +293,46 @@ class RackListView(ObjectListView): template_name = 'dcim/rack_list.html' +class RackElevationListView(View): + """ + Display a set of rack elevations side-by-side. + """ + + def get(self, request): + + racks = Rack.objects.select_related( + 'site', 'group', 'tenant', 'role' + ).prefetch_related( + 'devices__device_type' + ) + racks = filters.RackFilter(request.GET, racks).qs + total_count = racks.count() + + # Pagination + paginator = EnhancedPaginator(racks, 25) + page_number = request.GET.get('page', 1) + try: + page = paginator.page(page_number) + except PageNotAnInteger: + page = paginator.page(1) + except EmptyPage: + page = paginator.page(paginator.num_pages) + + # Determine rack face + if request.GET.get('face') == '1': + face_id = 1 + else: + face_id = 0 + + return render(request, 'dcim/rack_elevation_list.html', { + 'paginator': paginator, + 'page': page, + 'total_count': total_count, + 'face_id': face_id, + 'filter_form': forms.RackFilterForm(request.GET), + }) + + def rack(request, pk): rack = get_object_or_404(Rack.objects.select_related('site__region', 'tenant__group', 'group', 'role'), pk=pk) diff --git a/netbox/templates/_base.html b/netbox/templates/_base.html index df760de21..a7b0ceb5a 100644 --- a/netbox/templates/_base.html +++ b/netbox/templates/_base.html @@ -58,6 +58,7 @@