Browse Source

Implemented built-in CSV export for DCIM objects

Jeremy Stretch 9 years ago
parent
commit
943c7934f3

+ 79 - 9
netbox/dcim/models.py

@@ -103,6 +103,14 @@ class Site(models.Model):
     def get_absolute_url(self):
     def get_absolute_url(self):
         return reverse('dcim:site', args=[self.slug])
         return reverse('dcim:site', args=[self.slug])
 
 
+    def to_csv(self):
+        return ','.join([
+            self.name,
+            self.slug,
+            self.facility,
+            str(self.asn),
+        ])
+
     @property
     @property
     def count_prefixes(self):
     def count_prefixes(self):
         return self.prefixes.count()
         return self.prefixes.count()
@@ -172,6 +180,15 @@ class Rack(models.Model):
     def get_absolute_url(self):
     def get_absolute_url(self):
         return reverse('dcim:rack', args=[self.pk])
         return reverse('dcim:rack', args=[self.pk])
 
 
+    def to_csv(self):
+        return ','.join([
+            self.site.name,
+            self.group.name if self.group else '',
+            self.name,
+            self.facility_id or '',
+            str(self.u_height),
+        ])
+
     @property
     @property
     def units(self):
     def units(self):
         return reversed(range(1, self.u_height + 1))
         return reversed(range(1, self.u_height + 1))
@@ -446,15 +463,6 @@ class Device(models.Model):
     def get_absolute_url(self):
     def get_absolute_url(self):
         return reverse('dcim:device', args=[self.pk])
         return reverse('dcim:device', args=[self.pk])
 
 
-    @property
-    def display_name(self):
-        if self.name:
-            return self.name
-        elif self.position:
-            return "{} ({} U{})".format(self.device_type, self.rack, self.position)
-        else:
-            return "{} ({})".format(self.device_type, self.rack)
-
     def clean(self):
     def clean(self):
 
 
         # Validate position/face combination
         # Validate position/face combination
@@ -502,6 +510,38 @@ class Device(models.Model):
                            mgmt_only=template.mgmt_only) for template in self.device_type.interface_templates.all()]
                            mgmt_only=template.mgmt_only) for template in self.device_type.interface_templates.all()]
             )
             )
 
 
+    def to_csv(self):
+        return ','.join([
+            self.name or '',
+            self.device_role.name,
+            self.device_type.manufacturer.name,
+            self.device_type.model,
+            self.platform.name if self.platform else '',
+            self.serial,
+            self.rack.site.name,
+            self.rack.name,
+            str(self.position) if self.position else '',
+            self.get_face_display() or '',
+        ])
+
+    @property
+    def display_name(self):
+        if self.name:
+            return self.name
+        elif self.position:
+            return "{} ({} U{})".format(self.device_type, self.rack, self.position)
+        else:
+            return "{} ({})".format(self.device_type, self.rack)
+
+    @property
+    def identifier(self):
+        """
+        Return the device name if set; otherwise return the Device's primary key as {pk}
+        """
+        if self.name is not None:
+            return self.name
+        return '{{{}}}'.format(self.pk)
+
     def get_rpc_client(self):
     def get_rpc_client(self):
         """
         """
         Return the appropriate RPC (e.g. NETCONF, ssh, etc.) client for this device's platform, if one is defined.
         Return the appropriate RPC (e.g. NETCONF, ssh, etc.) client for this device's platform, if one is defined.
@@ -528,6 +568,16 @@ class ConsolePort(models.Model):
     def __unicode__(self):
     def __unicode__(self):
         return self.name
         return self.name
 
 
+    # Used for connections export
+    def to_csv(self):
+        return ','.join([
+            self.cs_port.device.identifier if self.cs_port else '',
+            self.cs_port.name if self.cs_port else '',
+            self.device.identifier,
+            self.name,
+            self.get_connection_status_display(),
+        ])
+
 
 
 class ConsoleServerPortManager(models.Manager):
 class ConsoleServerPortManager(models.Manager):
 
 
@@ -577,6 +627,16 @@ class PowerPort(models.Model):
     def __unicode__(self):
     def __unicode__(self):
         return self.name
         return self.name
 
 
+    # Used for connections export
+    def to_csv(self):
+        return ','.join([
+            self.power_outlet.device.identifier if self.power_outlet else '',
+            self.power_outlet.name if self.power_outlet else '',
+            self.device.identifier,
+            self.name,
+            self.get_connection_status_display(),
+        ])
+
 
 
 class PowerOutletManager(models.Manager):
 class PowerOutletManager(models.Manager):
 
 
@@ -695,6 +755,16 @@ class InterfaceConnection(models.Model):
         if self.interface_a == self.interface_b:
         if self.interface_a == self.interface_b:
             raise ValidationError("Cannot connect an interface to itself")
             raise ValidationError("Cannot connect an interface to itself")
 
 
+    # Used for connections export
+    def to_csv(self):
+        return ','.join([
+            self.interface_a.device.identifier,
+            self.interface_a.name,
+            self.interface_b.device.identifier,
+            self.interface_b.name,
+            self.get_connection_status_display(),
+        ])
+
 
 
 class Module(models.Model):
 class Module(models.Model):
     """
     """

+ 1 - 2
netbox/dcim/views.py

@@ -488,8 +488,7 @@ class PlatformBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 #
 #
 
 
 class DeviceListView(ObjectListView):
 class DeviceListView(ObjectListView):
-    queryset = Device.objects.select_related('device_type', 'device_type__manufacturer', 'device_role', 'rack',
+    queryset = Device.objects.select_related('device_type__manufacturer', 'device_role', 'rack__site', 'primary_ip')
-                                             'rack__site', 'primary_ip')
     filter = filters.DeviceFilter
     filter = filters.DeviceFilter
     filter_form = forms.DeviceFilterForm
     filter_form = forms.DeviceFilterForm
     table = tables.DeviceTable
     table = tables.DeviceTable

+ 6 - 12
netbox/templates/dcim/console_connections_list.html

@@ -5,19 +5,13 @@
 
 
 {% block content %}
 {% block content %}
 <div class="pull-right">
 <div class="pull-right">
-    {% if export_templates %}
+    {% if perms.dcim.change_consoleport %}
-        <div class="btn-group">
+        <a href="{% url 'dcim:console_connections_import' %}" class="btn btn-info">
-            <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+            <span class="glyphicon glyphicon-import" aria-hidden="true"></span>
-                <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
+            Import connections
-                Export connections <span class="caret"></span>
+        </a>
-            </button>
-            <ul class="dropdown-menu">
-                {% for et in export_templates %}
-                    <li><a href="{% url 'dcim:console_connections_list' %}?{% if request.GET %}{{ request.GET.urlencode }}&{% endif %}export={{ et.name }}">{{ et.name }}</a></li>
-                {% endfor %}
-            </ul>
-        </div>
     {% endif %}
     {% endif %}
+    {% include 'inc/export_button.html' with obj_type='connections' %}
 </div>
 </div>
 <h1>Console Connections</h1>
 <h1>Console Connections</h1>
 <div class="row">
 <div class="row">

+ 1 - 13
netbox/templates/dcim/device_list.html

@@ -15,19 +15,7 @@
             Import devices
             Import devices
         </a>
         </a>
     {% endif %}
     {% endif %}
-    {% if export_templates %}
+    {% include 'inc/export_button.html' with obj_type='devices' %}
-        <div class="btn-group">
-            <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
-                Export devices <span class="caret"></span>
-            </button>
-            <ul class="dropdown-menu">
-                {% for et in export_templates %}
-                    <li><a href="{% url 'dcim:device_list' %}?{% if request.GET %}{{ request.GET.urlencode }}&{% endif %}export={{ et.name }}">{{ et.name }}</a></li>
-                {% endfor %}
-            </ul>
-        </div>
-    {% endif %}
 </div>
 </div>
 <h1>Devices</h1>
 <h1>Devices</h1>
 <div class="row">
 <div class="row">

+ 6 - 12
netbox/templates/dcim/interface_connections_list.html

@@ -5,19 +5,13 @@
 
 
 {% block content %}
 {% block content %}
 <div class="pull-right">
 <div class="pull-right">
-    {% if export_templates %}
+    {% if perms.dcim.add_interfaceconnection %}
-        <div class="btn-group">
+        <a href="{% url 'dcim:interface_connections_import' %}" class="btn btn-info">
-            <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+            <span class="glyphicon glyphicon-import" aria-hidden="true"></span>
-                <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
+            Import connections
-                Export connections <span class="caret"></span>
+        </a>
-            </button>
-            <ul class="dropdown-menu">
-                {% for et in export_templates %}
-                    <li><a href="{% url 'dcim:interface_connections_list' %}?{% if request.GET %}{{ request.GET.urlencode }}&{% endif %}export={{ et.name }}">{{ et.name }}</a></li>
-                {% endfor %}
-            </ul>
-        </div>
     {% endif %}
     {% endif %}
+    {% include 'inc/export_button.html' with obj_type='connections' %}
 </div>
 </div>
 <h1>Interface Connections</h1>
 <h1>Interface Connections</h1>
 <div class="row">
 <div class="row">

+ 6 - 12
netbox/templates/dcim/power_connections_list.html

@@ -5,19 +5,13 @@
 
 
 {% block content %}
 {% block content %}
 <div class="pull-right">
 <div class="pull-right">
-    {% if export_templates %}
+    {% if perms.dcim.change_powerport %}
-        <div class="btn-group">
+        <a href="{% url 'dcim:power_connections_import' %}" class="btn btn-info">
-            <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+            <span class="glyphicon glyphicon-import" aria-hidden="true"></span>
-                <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
+            Import connections
-                Export connections <span class="caret"></span>
+        </a>
-            </button>
-            <ul class="dropdown-menu">
-                {% for et in export_templates %}
-                    <li><a href="{% url 'dcim:power_connections_list' %}?{% if request.GET %}{{ request.GET.urlencode }}&{% endif %}export={{ et.name }}">{{ et.name }}</a></li>
-                {% endfor %}
-            </ul>
-        </div>
     {% endif %}
     {% endif %}
+    {% include 'inc/export_button.html' with obj_type='connections' %}
 </div>
 </div>
 <h1>Power Connections</h1>
 <h1>Power Connections</h1>
 <div class="row">
 <div class="row">

+ 1 - 13
netbox/templates/dcim/rack_list.html

@@ -15,19 +15,7 @@
             Import racks
             Import racks
         </a>
         </a>
     {% endif %}
     {% endif %}
-    {% if export_templates %}
+    {% include 'inc/export_button.html' with obj_type='racks' %}
-        <div class="btn-group">
-            <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
-                Export racks <span class="caret"></span>
-            </button>
-            <ul class="dropdown-menu">
-                {% for et in export_templates %}
-                    <li><a href="{% url 'dcim:rack_list' %}?{% if request.GET %}{{ request.GET.urlencode }}&{% endif %}export={{ et.name }}">{{ et.name }}</a></li>
-                {% endfor %}
-            </ul>
-        </div>
-    {% endif %}
 </div>
 </div>
 <h1>Racks</h1>
 <h1>Racks</h1>
 <div class="row">
 <div class="row">

+ 1 - 13
netbox/templates/dcim/site_list.html

@@ -11,19 +11,7 @@
 			Add a site
 			Add a site
 		</a>
 		</a>
     {% endif %}
     {% endif %}
-    {% if export_templates %}
+    {% include 'inc/export_button.html' with obj_type='sites' %}
-        <div class="btn-group">
-            <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
-                Export sites <span class="caret"></span>
-            </button>
-            <ul class="dropdown-menu">
-                {% for et in export_templates %}
-                    <li><a href="{% url 'dcim:site_list' %}?{% if request.GET %}{{ request.GET.urlencode }}&{% endif %}export={{ et.name }}">{{ et.name }}</a></li>
-                {% endfor %}
-            </ul>
-        </div>
-    {% endif %}
 </div>
 </div>
 <h1>Sites</h1>
 <h1>Sites</h1>
 {% render_table table 'table.html' %}
 {% render_table table 'table.html' %}