Change DeviceType export from CSV to YAML

This commit is contained in:
Jeremy Stretch 2020-01-13 15:10:16 -05:00
parent 473d67354f
commit 0dad9f8901
3 changed files with 114 additions and 25 deletions

View File

@ -2,6 +2,7 @@ from collections import OrderedDict
from itertools import count, groupby from itertools import count, groupby
import svgwrite import svgwrite
import yaml
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
@ -25,15 +26,14 @@ from utilities.fields import ColorField
from utilities.managers import NaturalOrderingManager from utilities.managers import NaturalOrderingManager
from utilities.models import ChangeLoggedModel from utilities.models import ChangeLoggedModel
from utilities.utils import foreground_color, to_meters from utilities.utils import foreground_color, to_meters
from .device_components import (
CableTermination, ConsolePort, ConsoleServerPort, DeviceBay, FrontPort, Interface, InventoryItem, PowerOutlet,
PowerPort, RearPort,
)
from .device_component_templates import ( from .device_component_templates import (
ConsolePortTemplate, ConsoleServerPortTemplate, DeviceBayTemplate, FrontPortTemplate, InterfaceTemplate, ConsolePortTemplate, ConsoleServerPortTemplate, DeviceBayTemplate, FrontPortTemplate, InterfaceTemplate,
PowerOutletTemplate, PowerPortTemplate, RearPortTemplate, PowerOutletTemplate, PowerPortTemplate, RearPortTemplate,
) )
from .device_components import (
CableTermination, ConsolePort, ConsoleServerPort, DeviceBay, FrontPort, Interface, InventoryItem, PowerOutlet,
PowerPort, RearPort,
)
__all__ = ( __all__ = (
'Cable', 'Cable',
@ -1003,17 +1003,92 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel):
def get_absolute_url(self): def get_absolute_url(self):
return reverse('dcim:devicetype', args=[self.pk]) return reverse('dcim:devicetype', args=[self.pk])
def to_csv(self): def to_yaml(self):
return ( data = OrderedDict((
self.manufacturer.name, ('manufacturer', self.manufacturer.name),
self.model, ('model', self.model),
self.slug, ('slug', self.slug),
self.part_number, ('part_number', self.part_number),
self.u_height, ('u_height', self.u_height),
self.is_full_depth, ('is_full_depth', self.is_full_depth),
self.get_subdevice_role_display(), ('subdevice_role', self.subdevice_role),
self.comments, ('comments', self.comments),
) ))
# Component templates
if self.consoleport_templates.exists():
data['console-ports'] = [
{
'name': c.name,
'type': c.type,
}
for c in self.consoleport_templates.all()
]
if self.consoleserverport_templates.exists():
data['console-server-ports'] = [
{
'name': c.name,
'type': c.type,
}
for c in self.consoleserverport_templates.all()
]
if self.powerport_templates.exists():
data['power-ports'] = [
{
'name': c.name,
'type': c.type,
'maximum_draw': c.maximum_draw,
'allocated_draw': c.allocated_draw,
}
for c in self.powerport_templates.all()
]
if self.poweroutlet_templates.exists():
data['power-outlets'] = [
{
'name': c.name,
'type': c.type,
'power_port': c.power_port.name if c.power_port else None,
'feed_leg': c.feed_leg,
}
for c in self.poweroutlet_templates.all()
]
if self.interface_templates.exists():
data['interfaces'] = [
{
'name': c.name,
'type': c.type,
'mgmt_only': c.mgmt_only,
}
for c in self.interface_templates.all()
]
if self.frontport_templates.exists():
data['front-ports'] = [
{
'name': c.name,
'type': c.type,
'rear_port': c.rear_port.name,
'rear_port_position': c.rear_port_position,
}
for c in self.frontport_templates.all()
]
if self.rearport_templates.exists():
data['rear-ports'] = [
{
'name': c.name,
'type': c.type,
'positions': c.positions,
}
for c in self.rearport_templates.all()
]
if self.device_bay_templates.exists():
data['device-bays'] = [
{
'name': c.name,
}
for c in self.device_bay_templates.all()
]
return yaml.dump(dict(data), sort_keys=False)
def clean(self): def clean(self):

View File

@ -2056,7 +2056,8 @@ class ConsoleConnectionsListView(PermissionRequiredMixin, ObjectListView):
obj.get_connection_status_display(), obj.get_connection_status_display(),
]) ])
csv_data.append(csv) csv_data.append(csv)
return csv_data
return '\n'.join(csv_data)
class PowerConnectionsListView(PermissionRequiredMixin, ObjectListView): class PowerConnectionsListView(PermissionRequiredMixin, ObjectListView):
@ -2087,7 +2088,8 @@ class PowerConnectionsListView(PermissionRequiredMixin, ObjectListView):
obj.get_connection_status_display(), obj.get_connection_status_display(),
]) ])
csv_data.append(csv) csv_data.append(csv)
return csv_data
return '\n'.join(csv_data)
class InterfaceConnectionsListView(PermissionRequiredMixin, ObjectListView): class InterfaceConnectionsListView(PermissionRequiredMixin, ObjectListView):
@ -2126,7 +2128,8 @@ class InterfaceConnectionsListView(PermissionRequiredMixin, ObjectListView):
obj.get_connection_status_display(), obj.get_connection_status_display(),
]) ])
csv_data.append(csv) csv_data.append(csv)
return csv_data
return '\n'.join(csv_data)
# #

View File

@ -75,6 +75,14 @@ class ObjectListView(View):
table = None table = None
template_name = None template_name = None
def queryset_to_yaml(self):
"""
Export the queryset of objects as concatenated YAML documents.
"""
yaml_data = [obj.to_yaml() for obj in self.queryset]
return '---\n'.join(yaml_data)
def queryset_to_csv(self): def queryset_to_csv(self):
""" """
Export the queryset of objects as comma-separated value (CSV), using the model's to_csv() method. Export the queryset of objects as comma-separated value (CSV), using the model's to_csv() method.
@ -90,7 +98,7 @@ class ObjectListView(View):
data = csv_format(obj.to_csv()) data = csv_format(obj.to_csv())
csv_data.append(data) csv_data.append(data)
return csv_data return '\n'.join(csv_data)
def get(self, request): def get(self, request):
@ -121,13 +129,16 @@ class ObjectListView(View):
) )
) )
# Check for YAML export support
elif 'export' in request.GET and hasattr(model, 'to_yaml'):
response = HttpResponse(self.queryset_to_yaml(), content_type='text/yaml')
filename = 'netbox_{}.yaml'.format(self.queryset.model._meta.verbose_name_plural)
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
return response
# Fall back to built-in CSV formatting if export requested but no template specified # Fall back to built-in CSV formatting if export requested but no template specified
elif 'export' in request.GET and hasattr(model, 'to_csv'): elif 'export' in request.GET and hasattr(model, 'to_csv'):
data = self.queryset_to_csv() response = HttpResponse(self.queryset_to_csv(), content_type='text/csv')
response = HttpResponse(
'\n'.join(data),
content_type='text/csv'
)
filename = 'netbox_{}.csv'.format(self.queryset.model._meta.verbose_name_plural) filename = 'netbox_{}.csv'.format(self.queryset.model._meta.verbose_name_plural)
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename) response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
return response return response