Browse Source

Closes #913: Added headers to object CSV exports

Jeremy Stretch 7 years ago
parent
commit
08883d86ef

+ 4 - 0
netbox/circuits/models.py

@@ -52,6 +52,8 @@ class Provider(CreatedUpdatedModel, CustomFieldModel):
     comments = models.TextField(blank=True)
     custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
 
+    csv_headers = ['name', 'slug', 'asn', 'account', 'portal_url']
+
     class Meta:
         ordering = ['name']
 
@@ -107,6 +109,8 @@ class Circuit(CreatedUpdatedModel, CustomFieldModel):
     comments = models.TextField(blank=True)
     custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
 
+    csv_headers = ['cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'description']
+
     class Meta:
         ordering = ['provider', 'cid']
         unique_together = ['provider', 'cid']

+ 20 - 0
netbox/dcim/models.py

@@ -280,6 +280,10 @@ class Site(CreatedUpdatedModel, CustomFieldModel):
 
     objects = SiteManager()
 
+    csv_headers = [
+        'name', 'slug', 'region', 'tenant', 'facility', 'asn', 'contact_name', 'contact_phone', 'contact_email',
+    ]
+
     class Meta:
         ordering = ['name']
 
@@ -402,6 +406,10 @@ class Rack(CreatedUpdatedModel, CustomFieldModel):
 
     objects = RackManager()
 
+    csv_headers = [
+        'site', 'group_name', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height', 'desc_units',
+    ]
+
     class Meta:
         ordering = ['site', 'name']
         unique_together = [
@@ -981,6 +989,11 @@ class Device(CreatedUpdatedModel, CustomFieldModel):
 
     objects = DeviceManager()
 
+    csv_headers = [
+        'name', 'device_role', 'tenant', 'manufacturer', 'model_name', 'platform', 'serial', 'asset_tag', 'status',
+        'site', 'rack_group', 'rack_name', 'position', 'face',
+    ]
+
     class Meta:
         ordering = ['name']
         unique_together = ['rack', 'position', 'face']
@@ -1096,6 +1109,7 @@ class Device(CreatedUpdatedModel, CustomFieldModel):
             self.asset_tag,
             self.get_status_display(),
             self.site.name,
+            self.rack.group.name if self.rack and self.rack.group else None,
             self.rack.name if self.rack else None,
             self.position,
             self.get_face_display(),
@@ -1162,6 +1176,8 @@ class ConsolePort(models.Model):
                                    verbose_name='Console server port', blank=True, null=True)
     connection_status = models.NullBooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED)
 
+    csv_headers = ['console_server', 'cs_port', 'device', 'console_port', 'connection_status']
+
     class Meta:
         ordering = ['device', 'name']
         unique_together = ['device', 'name']
@@ -1231,6 +1247,8 @@ class PowerPort(models.Model):
                                         blank=True, null=True)
     connection_status = models.NullBooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED)
 
+    csv_headers = ['pdu', 'power_outlet', 'device', 'power_port', 'connection_status']
+
     class Meta:
         ordering = ['device', 'name']
         unique_together = ['device', 'name']
@@ -1392,6 +1410,8 @@ class InterfaceConnection(models.Model):
     connection_status = models.BooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED,
                                             verbose_name='Status')
 
+    csv_headers = ['device_a', 'interface_a', 'device_b', 'interface_b', 'connection_status']
+
     def clean(self):
         try:
             if self.interface_a == self.interface_b:

+ 14 - 1
netbox/ipam/models.py

@@ -89,6 +89,8 @@ class VRF(CreatedUpdatedModel, CustomFieldModel):
     description = models.CharField(max_length=100, blank=True)
     custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
 
+    csv_headers = ['name', 'rd', 'tenant', 'enforce_unique', 'description']
+
     class Meta:
         ordering = ['name']
         verbose_name = 'VRF'
@@ -146,6 +148,8 @@ class Aggregate(CreatedUpdatedModel, CustomFieldModel):
     description = models.CharField(max_length=100, blank=True)
     custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
 
+    csv_headers = ['prefix', 'rir', 'date_added', 'description']
+
     class Meta:
         ordering = ['family', 'prefix']
 
@@ -297,6 +301,10 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel):
 
     objects = PrefixQuerySet.as_manager()
 
+    csv_headers = [
+        'prefix', 'vrf', 'tenant', 'site', 'vlan_group', 'vlan_vid', 'status', 'role', 'is_pool', 'description',
+    ]
+
     class Meta:
         ordering = ['vrf', 'family', 'prefix']
         verbose_name_plural = 'prefixes'
@@ -424,6 +432,8 @@ class IPAddress(CreatedUpdatedModel, CustomFieldModel):
 
     objects = IPAddressManager()
 
+    csv_headers = ['address', 'vrf', 'tenant', 'status', 'device', 'interface_name', 'is_primary', 'description']
+
     class Meta:
         ordering = ['family', 'address']
         verbose_name = 'IP address'
@@ -462,11 +472,12 @@ class IPAddress(CreatedUpdatedModel, CustomFieldModel):
     def to_csv(self):
 
         # Determine if this IP is primary for a Device
-        is_primary = False
         if self.family == 4 and getattr(self, 'primary_ip4_for', False):
             is_primary = True
         elif self.family == 6 and getattr(self, 'primary_ip6_for', False):
             is_primary = True
+        else:
+            is_primary = False
 
         return csv_format([
             self.address,
@@ -537,6 +548,8 @@ class VLAN(CreatedUpdatedModel, CustomFieldModel):
     description = models.CharField(max_length=100, blank=True)
     custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
 
+    csv_headers = ['site', 'group_name', 'vid', 'name', 'tenant', 'status', 'role', 'description']
+
     class Meta:
         ordering = ['site', 'group', 'vid']
         unique_together = [

+ 1 - 0
netbox/secrets/models.py

@@ -291,6 +291,7 @@ class Secret(CreatedUpdatedModel):
     hash = models.CharField(max_length=128, editable=False)
 
     plaintext = None
+    csv_headers = ['device', 'role', 'name', 'plaintext']
 
     class Meta:
         ordering = ['device', 'role', 'name']

+ 2 - 0
netbox/tenancy/models.py

@@ -41,6 +41,8 @@ class Tenant(CreatedUpdatedModel, CustomFieldModel):
     comments = models.TextField(blank=True)
     custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
 
+    csv_headers = ['name', 'slug', 'group', 'description']
+
     class Meta:
         ordering = ['group', 'name']
 

+ 3 - 1
netbox/utilities/views.py

@@ -102,7 +102,9 @@ class ObjectListView(View):
                                .format(et.name))
         # Fall back to built-in CSV export
         elif 'export' in request.GET and hasattr(model, 'to_csv'):
-            output = '\n'.join([obj.to_csv() for obj in self.queryset])
+            headers = getattr(model, 'csv_headers', None)
+            output = ','.join(headers) + '\n' if headers else ''
+            output += '\n'.join([obj.to_csv() for obj in self.queryset])
             response = HttpResponse(
                 output,
                 content_type='text/csv'