Просмотр исходного кода

CSV import/export custom fields

Saria Hajjar 6 лет назад
Родитель
Сommit
f1d5e28f13

+ 3 - 3
netbox/circuits/forms.py

@@ -46,7 +46,7 @@ class ProviderForm(BootstrapMixin, CustomFieldForm):
         }
         }
 
 
 
 
-class ProviderCSVForm(forms.ModelForm):
+class ProviderCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -144,7 +144,7 @@ class CircuitTypeForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class CircuitTypeCSVForm(forms.ModelForm):
+class CircuitTypeCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -187,7 +187,7 @@ class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class CircuitCSVForm(forms.ModelForm):
+class CircuitCSVForm(CustomFieldForm):
     provider = forms.ModelChoiceField(
     provider = forms.ModelChoiceField(
         queryset=Provider.objects.all(),
         queryset=Provider.objects.all(),
         to_field_name='name',
         to_field_name='name',

+ 14 - 14
netbox/dcim/forms.py

@@ -151,7 +151,7 @@ class RegionForm(BootstrapMixin, forms.ModelForm):
         }
         }
 
 
 
 
-class RegionCSVForm(forms.ModelForm):
+class RegionCSVForm(CustomFieldForm):
     parent = forms.ModelChoiceField(
     parent = forms.ModelChoiceField(
         queryset=Region.objects.all(),
         queryset=Region.objects.all(),
         required=False,
         required=False,
@@ -231,7 +231,7 @@ class SiteForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class SiteCSVForm(forms.ModelForm):
+class SiteCSVForm(CustomFieldForm):
     status = CSVChoiceField(
     status = CSVChoiceField(
         choices=SITE_STATUS_CHOICES,
         choices=SITE_STATUS_CHOICES,
         required=False,
         required=False,
@@ -355,7 +355,7 @@ class RackGroupForm(BootstrapMixin, forms.ModelForm):
         }
         }
 
 
 
 
-class RackGroupCSVForm(forms.ModelForm):
+class RackGroupCSVForm(CustomFieldForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -411,7 +411,7 @@ class RackRoleForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class RackRoleCSVForm(forms.ModelForm):
+class RackRoleCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -472,7 +472,7 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class RackCSVForm(forms.ModelForm):
+class RackCSVForm(CustomFieldForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -852,7 +852,7 @@ class ManufacturerForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class ManufacturerCSVForm(forms.ModelForm):
+class ManufacturerCSVForm(CustomFieldForm):
 
 
     class Meta:
     class Meta:
         model = Manufacturer
         model = Manufacturer
@@ -890,7 +890,7 @@ class DeviceTypeForm(BootstrapMixin, CustomFieldForm):
         }
         }
 
 
 
 
-class DeviceTypeCSVForm(forms.ModelForm):
+class DeviceTypeCSVForm(CustomFieldForm):
     manufacturer = forms.ModelChoiceField(
     manufacturer = forms.ModelChoiceField(
         queryset=Manufacturer.objects.all(),
         queryset=Manufacturer.objects.all(),
         required=True,
         required=True,
@@ -1308,7 +1308,7 @@ class DeviceRoleForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class DeviceRoleCSVForm(forms.ModelForm):
+class DeviceRoleCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -1342,7 +1342,7 @@ class PlatformForm(BootstrapMixin, forms.ModelForm):
         }
         }
 
 
 
 
-class PlatformCSVForm(forms.ModelForm):
+class PlatformCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
     manufacturer = forms.ModelChoiceField(
     manufacturer = forms.ModelChoiceField(
         queryset=Manufacturer.objects.all(),
         queryset=Manufacturer.objects.all(),
@@ -1564,7 +1564,7 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldForm):
             self.initial['rack'] = self.instance.parent_bay.device.rack_id
             self.initial['rack'] = self.instance.parent_bay.device.rack_id
 
 
 
 
-class BaseDeviceCSVForm(forms.ModelForm):
+class BaseDeviceCSVForm(CustomFieldForm):
     device_role = forms.ModelChoiceField(
     device_role = forms.ModelChoiceField(
         queryset=DeviceRole.objects.all(),
         queryset=DeviceRole.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -2919,7 +2919,7 @@ class CableForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class CableCSVForm(forms.ModelForm):
+class CableCSVForm(CustomFieldForm):
 
 
     # Termination A
     # Termination A
     side_a_device = FlexibleModelChoiceField(
     side_a_device = FlexibleModelChoiceField(
@@ -3294,7 +3294,7 @@ class InventoryItemForm(BootstrapMixin, forms.ModelForm):
         }
         }
 
 
 
 
-class InventoryItemCSVForm(forms.ModelForm):
+class InventoryItemCSVForm(CustomFieldForm):
     device = FlexibleModelChoiceField(
     device = FlexibleModelChoiceField(
         queryset=Device.objects.all(),
         queryset=Device.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -3623,7 +3623,7 @@ class PowerPanelForm(BootstrapMixin, forms.ModelForm):
         }
         }
 
 
 
 
-class PowerPanelCSVForm(forms.ModelForm):
+class PowerPanelCSVForm(CustomFieldForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -3747,7 +3747,7 @@ class PowerFeedForm(BootstrapMixin, CustomFieldForm):
             self.initial['site'] = self.instance.power_panel.site
             self.initial['site'] = self.instance.power_panel.site
 
 
 
 
-class PowerFeedCSVForm(forms.ModelForm):
+class PowerFeedCSVForm(CustomFieldForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         to_field_name='name',
         to_field_name='name',

+ 8 - 8
netbox/ipam/forms.py

@@ -48,7 +48,7 @@ class VRFForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class VRFCSVForm(forms.ModelForm):
+class VRFCSVForm(CustomFieldForm):
     tenant = forms.ModelChoiceField(
     tenant = forms.ModelChoiceField(
         queryset=Tenant.objects.all(),
         queryset=Tenant.objects.all(),
         required=False,
         required=False,
@@ -118,7 +118,7 @@ class RIRForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class RIRCSVForm(forms.ModelForm):
+class RIRCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -165,7 +165,7 @@ class AggregateForm(BootstrapMixin, CustomFieldForm):
         }
         }
 
 
 
 
-class AggregateCSVForm(forms.ModelForm):
+class AggregateCSVForm(CustomFieldForm):
     rir = forms.ModelChoiceField(
     rir = forms.ModelChoiceField(
         queryset=RIR.objects.all(),
         queryset=RIR.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -247,7 +247,7 @@ class RoleForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class RoleCSVForm(forms.ModelForm):
+class RoleCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -340,7 +340,7 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         self.fields['vrf'].empty_label = 'Global'
         self.fields['vrf'].empty_label = 'Global'
 
 
 
 
-class PrefixCSVForm(forms.ModelForm):
+class PrefixCSVForm(CustomFieldForm):
     vrf = FlexibleModelChoiceField(
     vrf = FlexibleModelChoiceField(
         queryset=VRF.objects.all(),
         queryset=VRF.objects.all(),
         to_field_name='rd',
         to_field_name='rd',
@@ -759,7 +759,7 @@ class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         self.fields['vrf'].empty_label = 'Global'
         self.fields['vrf'].empty_label = 'Global'
 
 
 
 
-class IPAddressCSVForm(forms.ModelForm):
+class IPAddressCSVForm(CustomFieldForm):
     vrf = FlexibleModelChoiceField(
     vrf = FlexibleModelChoiceField(
         queryset=VRF.objects.all(),
         queryset=VRF.objects.all(),
         to_field_name='rd',
         to_field_name='rd',
@@ -1025,7 +1025,7 @@ class VLANGroupForm(BootstrapMixin, forms.ModelForm):
         }
         }
 
 
 
 
-class VLANGroupCSVForm(forms.ModelForm):
+class VLANGroupCSVForm(CustomFieldForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         required=False,
         required=False,
@@ -1122,7 +1122,7 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class VLANCSVForm(forms.ModelForm):
+class VLANCSVForm(CustomFieldForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         required=False,
         required=False,

+ 2 - 2
netbox/secrets/forms.py

@@ -50,7 +50,7 @@ class SecretRoleForm(BootstrapMixin, forms.ModelForm):
         }
         }
 
 
 
 
-class SecretRoleCSVForm(forms.ModelForm):
+class SecretRoleCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -113,7 +113,7 @@ class SecretForm(BootstrapMixin, CustomFieldForm):
             })
             })
 
 
 
 
-class SecretCSVForm(forms.ModelForm):
+class SecretCSVForm(CustomFieldForm):
     device = FlexibleModelChoiceField(
     device = FlexibleModelChoiceField(
         queryset=Device.objects.all(),
         queryset=Device.objects.all(),
         to_field_name='name',
         to_field_name='name',

+ 2 - 2
netbox/tenancy/forms.py

@@ -23,7 +23,7 @@ class TenantGroupForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class TenantGroupCSVForm(forms.ModelForm):
+class TenantGroupCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -57,7 +57,7 @@ class TenantForm(BootstrapMixin, CustomFieldForm):
         }
         }
 
 
 
 
-class TenantCSVForm(forms.ModelForm):
+class TenantCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
     group = forms.ModelChoiceField(
     group = forms.ModelChoiceField(
         queryset=TenantGroup.objects.all(),
         queryset=TenantGroup.objects.all(),

+ 3 - 0
netbox/utilities/templatetags/helpers.py

@@ -149,6 +149,9 @@ def example_choices(field, arg=3):
             break
             break
         if not value or not label:
         if not value or not label:
             continue
             continue
+        # Handling for custom fields
+        if hasattr(label, 'value'):
+            label = label.value
         examples.append(label)
         examples.append(label)
     return ', '.join(examples) or 'None'
     return ', '.join(examples) or 'None'
 
 

+ 15 - 2
netbox/utilities/views.py

@@ -78,15 +78,28 @@ class ObjectListView(View):
         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.
         """
         """
         csv_data = []
         csv_data = []
+        custom_fields = []
 
 
         # Start with the column headers
         # Start with the column headers
         headers = ','.join(self.queryset.model.csv_headers)
         headers = ','.join(self.queryset.model.csv_headers)
+
+        # Add custom field headers
+        content_type = ContentType.objects.get_for_model(self.queryset.model)
+
+        for custom_field in CustomField.objects.filter(obj_type=content_type):
+            headers += ',cf_{}'.format(custom_field.name)
+            custom_fields.append(custom_field.name)
+
         csv_data.append(headers)
         csv_data.append(headers)
 
 
         # Iterate through the queryset appending each object
         # Iterate through the queryset appending each object
         for obj in self.queryset:
         for obj in self.queryset:
-            data = csv_format(obj.to_csv())
-            csv_data.append(data)
+            data = obj.to_csv()
+
+            for custom_field in custom_fields:
+                data += (obj.cf.get(custom_field, ''),)
+
+            csv_data.append(csv_format(data))
 
 
         return csv_data
         return csv_data
 
 

+ 4 - 4
netbox/virtualization/forms.py

@@ -37,7 +37,7 @@ class ClusterTypeForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class ClusterTypeCSVForm(forms.ModelForm):
+class ClusterTypeCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -62,7 +62,7 @@ class ClusterGroupForm(BootstrapMixin, forms.ModelForm):
         ]
         ]
 
 
 
 
-class ClusterGroupCSVForm(forms.ModelForm):
+class ClusterGroupCSVForm(CustomFieldForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -101,7 +101,7 @@ class ClusterForm(BootstrapMixin, CustomFieldForm):
         }
         }
 
 
 
 
-class ClusterCSVForm(forms.ModelForm):
+class ClusterCSVForm(CustomFieldForm):
     type = forms.ModelChoiceField(
     type = forms.ModelChoiceField(
         queryset=ClusterType.objects.all(),
         queryset=ClusterType.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -416,7 +416,7 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
             self.fields['primary_ip6'].widget.attrs['readonly'] = True
             self.fields['primary_ip6'].widget.attrs['readonly'] = True
 
 
 
 
-class VirtualMachineCSVForm(forms.ModelForm):
+class VirtualMachineCSVForm(CustomFieldForm):
     status = CSVChoiceField(
     status = CSVChoiceField(
         choices=VM_STATUS_CHOICES,
         choices=VM_STATUS_CHOICES,
         required=False,
         required=False,