Parcourir la source

Implemented built-in CSV export for DCIM objects

Jeremy Stretch il y a 8 ans
Parent
commit
943c7934f3

+ 79 - 9
netbox/dcim/models.py

@@ -103,6 +103,14 @@ class Site(models.Model):
     def get_absolute_url(self):
         return reverse('dcim:site', args=[self.slug])
 
+    def to_csv(self):
+        return ','.join([
+            self.name,
+            self.slug,
+            self.facility,
+            str(self.asn),
+        ])
+
     @property
     def count_prefixes(self):
         return self.prefixes.count()
@@ -172,6 +180,15 @@ class Rack(models.Model):
     def get_absolute_url(self):
         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
     def units(self):
         return reversed(range(1, self.u_height + 1))
@@ -446,15 +463,6 @@ class Device(models.Model):
     def get_absolute_url(self):
         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):
 
         # 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()]
             )
 
+    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):
         """
         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):
         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):
 
@@ -577,6 +627,16 @@ class PowerPort(models.Model):
     def __unicode__(self):
         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):
 
@@ -695,6 +755,16 @@ class InterfaceConnection(models.Model):
         if self.interface_a == self.interface_b:
             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):
     """

+ 1 - 2
netbox/dcim/views.py

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

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

@@ -5,19 +5,13 @@
 
 {% block content %}
 <div class="pull-right">
-    {% if export_templates %}
-        <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 connections <span class="caret"></span>
-            </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>
+    {% if perms.dcim.change_consoleport %}
+        <a href="{% url 'dcim:console_connections_import' %}" class="btn btn-info">
+            <span class="glyphicon glyphicon-import" aria-hidden="true"></span>
+            Import connections
+        </a>
     {% endif %}
+    {% include 'inc/export_button.html' with obj_type='connections' %}
 </div>
 <h1>Console Connections</h1>
 <div class="row">

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

@@ -15,19 +15,7 @@
             Import devices
         </a>
     {% endif %}
-    {% if export_templates %}
-        <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 %}
+    {% include 'inc/export_button.html' with obj_type='devices' %}
 </div>
 <h1>Devices</h1>
 <div class="row">

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

@@ -5,19 +5,13 @@
 
 {% block content %}
 <div class="pull-right">
-    {% if export_templates %}
-        <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 connections <span class="caret"></span>
-            </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>
+    {% if perms.dcim.add_interfaceconnection %}
+        <a href="{% url 'dcim:interface_connections_import' %}" class="btn btn-info">
+            <span class="glyphicon glyphicon-import" aria-hidden="true"></span>
+            Import connections
+        </a>
     {% endif %}
+    {% include 'inc/export_button.html' with obj_type='connections' %}
 </div>
 <h1>Interface Connections</h1>
 <div class="row">

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

@@ -5,19 +5,13 @@
 
 {% block content %}
 <div class="pull-right">
-    {% if export_templates %}
-        <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 connections <span class="caret"></span>
-            </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>
+    {% if perms.dcim.change_powerport %}
+        <a href="{% url 'dcim:power_connections_import' %}" class="btn btn-info">
+            <span class="glyphicon glyphicon-import" aria-hidden="true"></span>
+            Import connections
+        </a>
     {% endif %}
+    {% include 'inc/export_button.html' with obj_type='connections' %}
 </div>
 <h1>Power Connections</h1>
 <div class="row">

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

@@ -15,19 +15,7 @@
             Import racks
         </a>
     {% endif %}
-    {% if export_templates %}
-        <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 %}
+    {% include 'inc/export_button.html' with obj_type='racks' %}
 </div>
 <h1>Racks</h1>
 <div class="row">

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

@@ -11,19 +11,7 @@
 			Add a site
 		</a>
     {% endif %}
-    {% if export_templates %}
-        <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 %}
+    {% include 'inc/export_button.html' with obj_type='sites' %}
 </div>
 <h1>Sites</h1>
 {% render_table table 'table.html' %}