Parcourir la source

Converted site/rack/device import views to new scheme

Jeremy Stretch il y a 8 ans
Parent
commit
7e660d4d8e

+ 122 - 66
netbox/dcim/forms.py

@@ -107,29 +107,34 @@ class SiteForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
 
 
-class SiteFromCSVForm(forms.ModelForm):
+class SiteCSVForm(forms.ModelForm):
     region = forms.ModelChoiceField(
-        Region.objects.all(), to_field_name='name', required=False, error_messages={
-            'invalid_choice': 'Tenant not found.'
+        queryset=Region.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned region',
+        error_messages={
+            'invalid_choice': 'Region not found.',
         }
     )
     tenant = forms.ModelChoiceField(
-        Tenant.objects.all(), to_field_name='name', required=False, error_messages={
-            'invalid_choice': 'Tenant not found.'
+        queryset=Tenant.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned tenant',
+        error_messages={
+            'invalid_choice': 'Tenant not found.',
         }
     )
 
     class Meta:
         model = Site
         fields = [
-            'name', 'slug', 'region', 'tenant', 'facility', 'asn', 'contact_name', 'contact_phone', 'contact_email',
+            'name', 'slug', 'region', 'tenant', 'facility', 'asn', 'physical_address', 'shipping_address',
+            'contact_name', 'contact_phone', 'contact_email', 'comments',
         ]
 
 
-class SiteImportForm(BootstrapMixin, BulkImportForm):
-    csv = CSVDataField(csv_form=SiteFromCSVForm)
-
-
 class SiteBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Site.objects.all(), widget=forms.MultipleHiddenInput)
     region = TreeNodeChoiceField(queryset=Region.objects.all(), required=False)
@@ -217,35 +222,62 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
 
 
-class RackFromCSVForm(forms.ModelForm):
-    site = forms.ModelChoiceField(queryset=Site.objects.all(), to_field_name='name',
-                                  error_messages={'invalid_choice': 'Site not found.'})
-    group_name = forms.CharField(required=False)
-    tenant = forms.ModelChoiceField(Tenant.objects.all(), to_field_name='name', required=False,
-                                    error_messages={'invalid_choice': 'Tenant not found.'})
-    role = forms.ModelChoiceField(RackRole.objects.all(), to_field_name='name', required=False,
-                                  error_messages={'invalid_choice': 'Role not found.'})
+class RackCSVForm(forms.ModelForm):
+    site = forms.ModelChoiceField(
+        queryset=Site.objects.all(),
+        to_field_name='name',
+        help_text='Name of parent site',
+        error_messages={
+            'invalid_choice': 'Site not found.',
+        }
+    )
+    group = forms.ModelChoiceField(
+        queryset=RackGroup.objects.all(),
+        to_field_name='name',
+        required=False,
+        help_text='Name of parent group',
+        error_messages={
+            'invalid_choice': 'Rack group not found.',
+        }
+    )
+    tenant = forms.ModelChoiceField(
+        queryset=Tenant.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned tenant',
+        error_messages={
+            'invalid_choice': 'Tenant not found.',
+        }
+    )
+    role = forms.ModelChoiceField(
+        queryset=RackRole.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned role',
+        error_messages={
+            'invalid_choice': 'Role not found.',
+        }
+    )
     type = forms.CharField(required=False)
 
     class Meta:
         model = Rack
-        fields = ['site', 'group_name', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height',
-                  'desc_units']
+        fields = [
+            'site', 'group', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height', 'desc_units',
+        ]
 
-    def clean(self):
+    def clean_group(self):
 
         site = self.cleaned_data.get('site')
-        group = self.cleaned_data.get('group_name')
+        group = self.cleaned_data.get('group')
 
-        # Validate rack group
-        if site and group:
-            try:
-                self.instance.group = RackGroup.objects.get(site=site, name=group)
-            except RackGroup.DoesNotExist:
-                self.add_error('group_name', "Invalid rack group ({})".format(group))
+        if group and group.site != site:
+            raise ValidationError("Invalid group for site {}: {}".format(site, group))
 
     def clean_type(self):
+
         rack_type = self.cleaned_data['type']
+
         if not rack_type:
             return None
         try:
@@ -258,10 +290,6 @@ class RackFromCSVForm(forms.ModelForm):
             ))
 
 
-class RackImportForm(BootstrapMixin, BulkImportForm):
-    csv = CSVDataField(csv_form=RackFromCSVForm)
-
-
 class RackBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Rack.objects.all(), widget=forms.MultipleHiddenInput)
     site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, label='Site')
@@ -663,25 +691,47 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldForm):
             self.initial['rack'] = self.instance.parent_bay.device.rack_id
 
 
-class BaseDeviceFromCSVForm(forms.ModelForm):
+class BaseDeviceCSVForm(forms.ModelForm):
     device_role = forms.ModelChoiceField(
-        queryset=DeviceRole.objects.all(), to_field_name='name',
-        error_messages={'invalid_choice': 'Invalid device role.'}
+        queryset=DeviceRole.objects.all(),
+        to_field_name='name',
+        help_text='Name of assigned role',
+        error_messages={
+            'invalid_choice': 'Invalid device role.',
+        }
     )
     tenant = forms.ModelChoiceField(
-        Tenant.objects.all(), to_field_name='name', required=False,
-        error_messages={'invalid_choice': 'Tenant not found.'}
+        queryset=Tenant.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned tenant',
+        error_messages={
+            'invalid_choice': 'Tenant not found.',
+        }
     )
     manufacturer = forms.ModelChoiceField(
-        queryset=Manufacturer.objects.all(), to_field_name='name',
-        error_messages={'invalid_choice': 'Invalid manufacturer.'}
+        queryset=Manufacturer.objects.all(),
+        to_field_name='name',
+        help_text='Manufacturer name',
+        error_messages={
+            'invalid_choice': 'Invalid manufacturer.',
+        }
+    )
+    model_name = forms.CharField(
+        help_text='Model name'
     )
-    model_name = forms.CharField()
     platform = forms.ModelChoiceField(
-        queryset=Platform.objects.all(), required=False, to_field_name='name',
-        error_messages={'invalid_choice': 'Invalid platform.'}
+        queryset=Platform.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned platform',
+        error_messages={
+            'invalid_choice': 'Invalid platform.',
+        }
+    )
+    status = forms.CharField(
+        help_text='Status name'
     )
-    status = forms.CharField()
 
     class Meta:
         fields = []
@@ -707,16 +757,25 @@ class BaseDeviceFromCSVForm(forms.ModelForm):
             raise ValidationError("Invalid status: {}".format(self.cleaned_data['status']))
 
 
-class DeviceFromCSVForm(BaseDeviceFromCSVForm):
+class DeviceCSVForm(BaseDeviceCSVForm):
     site = forms.ModelChoiceField(
-        queryset=Site.objects.all(), to_field_name='name', error_messages={
+        queryset=Site.objects.all(),
+        to_field_name='name',
+        help_text='Name of parent site',
+        error_messages={
             'invalid_choice': 'Invalid site name.',
         }
     )
-    rack_name = forms.CharField(required=False)
-    face = forms.CharField(required=False)
+    rack_name = forms.CharField(
+        required=False,
+        help_text='Name of parent rack'
+    )
+    face = forms.CharField(
+        required=False,
+        help_text='Mounted rack face (front or rear)'
+    )
 
-    class Meta(BaseDeviceFromCSVForm.Meta):
+    class Meta(BaseDeviceCSVForm.Meta):
         fields = [
             'name', 'device_role', 'tenant', 'manufacturer', 'model_name', 'platform', 'serial', 'asset_tag', 'status',
             'site', 'rack_name', 'position', 'face',
@@ -724,7 +783,7 @@ class DeviceFromCSVForm(BaseDeviceFromCSVForm):
 
     def clean(self):
 
-        super(DeviceFromCSVForm, self).clean()
+        super(DeviceCSVForm, self).clean()
 
         site = self.cleaned_data.get('site')
         rack_name = self.cleaned_data.get('rack_name')
@@ -749,18 +808,20 @@ class DeviceFromCSVForm(BaseDeviceFromCSVForm):
             raise forms.ValidationError('Invalid rack face ({}); must be "front" or "rear".'.format(face))
 
 
-class ChildDeviceFromCSVForm(BaseDeviceFromCSVForm):
+class ChildDeviceCSVForm(BaseDeviceCSVForm):
     parent = FlexibleModelChoiceField(
         queryset=Device.objects.all(),
         to_field_name='name',
-        required=False,
+        help_text='Name of parent device',
         error_messages={
-            'invalid_choice': 'Parent device not found.'
+            'invalid_choice': 'Parent device not found.',
         }
     )
-    device_bay_name = forms.CharField(required=False)
+    device_bay_name = forms.CharField(
+        help_text='Name of device bay',
+    )
 
-    class Meta(BaseDeviceFromCSVForm.Meta):
+    class Meta(BaseDeviceCSVForm.Meta):
         fields = [
             'name', 'device_role', 'tenant', 'manufacturer', 'model_name', 'platform', 'serial', 'asset_tag', 'status',
             'parent', 'device_bay_name',
@@ -768,7 +829,7 @@ class ChildDeviceFromCSVForm(BaseDeviceFromCSVForm):
 
     def clean(self):
 
-        super(ChildDeviceFromCSVForm, self).clean()
+        super(ChildDeviceCSVForm, self).clean()
 
         parent = self.cleaned_data.get('parent')
         device_bay_name = self.cleaned_data.get('device_bay_name')
@@ -778,20 +839,15 @@ class ChildDeviceFromCSVForm(BaseDeviceFromCSVForm):
             try:
                 device_bay = DeviceBay.objects.get(device=parent, name=device_bay_name)
                 if device_bay.installed_device:
-                    self.add_error('device_bay_name',
-                                   "Device bay ({} {}) is already occupied".format(parent, device_bay_name))
+                    self.add_error(
+                        'device_bay_name', "Device bay ({} {}) is already occupied".format(parent, device_bay_name)
+                    )
                 else:
                     self.instance.parent_bay = device_bay
             except DeviceBay.DoesNotExist:
-                self.add_error('device_bay_name', "Parent device/bay ({} {}) not found".format(parent, device_bay_name))
-
-
-class DeviceImportForm(BootstrapMixin, BulkImportForm):
-    csv = CSVDataField(csv_form=DeviceFromCSVForm)
-
-
-class ChildDeviceImportForm(BootstrapMixin, BulkImportForm):
-    csv = CSVDataField(csv_form=ChildDeviceFromCSVForm)
+                self.add_error(
+                    'device_bay_name', "Parent device/bay ({} {}) not found".format(parent, device_bay_name)
+                )
 
 
 class DeviceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):

+ 11 - 13
netbox/dcim/views.py

@@ -23,14 +23,14 @@ from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_S
 from utilities.forms import ConfirmationForm
 from utilities.paginator import EnhancedPaginator
 from utilities.views import (
-    BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
+    BulkDeleteView, BulkEditView, BulkImportView, BulkImportView2, ObjectDeleteView, ObjectEditView, ObjectListView,
 )
 from . import filters, forms, tables
 from .models import (
     CONNECTION_STATUS_CONNECTED, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device,
     DeviceBay, DeviceBayTemplate, DeviceRole, DeviceType, Interface, InterfaceConnection, InterfaceTemplate,
-    Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup,
-    RackReservation, RackRole, Region, Site,
+    Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack,
+    RackGroup, RackReservation, RackRole, Region, Site,
 )
 
 
@@ -217,11 +217,10 @@ class SiteDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     default_return_url = 'dcim:site_list'
 
 
-class SiteBulkImportView(PermissionRequiredMixin, BulkImportView):
+class SiteBulkImportView(PermissionRequiredMixin, BulkImportView2):
     permission_required = 'dcim.add_site'
-    form = forms.SiteImportForm
+    model_form = forms.SiteCSVForm
     table = tables.SiteTable
-    template_name = 'dcim/site_import.html'
     default_return_url = 'dcim:site_list'
 
 
@@ -388,11 +387,10 @@ class RackDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     default_return_url = 'dcim:rack_list'
 
 
-class RackBulkImportView(PermissionRequiredMixin, BulkImportView):
+class RackBulkImportView(PermissionRequiredMixin, BulkImportView2):
     permission_required = 'dcim.add_rack'
-    form = forms.RackImportForm
+    model_form = forms.RackCSVForm
     table = tables.RackImportTable
-    template_name = 'dcim/rack_import.html'
     default_return_url = 'dcim:rack_list'
 
 
@@ -864,17 +862,17 @@ class DeviceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     default_return_url = 'dcim:device_list'
 
 
-class DeviceBulkImportView(PermissionRequiredMixin, BulkImportView):
+class DeviceBulkImportView(PermissionRequiredMixin, BulkImportView2):
     permission_required = 'dcim.add_device'
-    form = forms.DeviceImportForm
+    model_form = forms.DeviceCSVForm
     table = tables.DeviceImportTable
     template_name = 'dcim/device_import.html'
     default_return_url = 'dcim:device_list'
 
 
-class ChildDeviceBulkImportView(PermissionRequiredMixin, BulkImportView):
+class ChildDeviceBulkImportView(PermissionRequiredMixin, BulkImportView2):
     permission_required = 'dcim.add_device'
-    form = forms.ChildDeviceImportForm
+    model_form = forms.ChildDeviceCSVForm
     table = tables.DeviceImportTable
     template_name = 'dcim/device_import_child.html'
     default_return_url = 'dcim:device_list'

+ 3 - 101
netbox/templates/dcim/device_import.html

@@ -1,103 +1,5 @@
-{% extends '_base.html' %}
-{% load form_helpers %}
+{% extends 'utilities/obj_import.html' %}
 
-{% block title %}Device Import{% endblock %}
-
-{% block content %}
-{% include 'dcim/inc/device_import_header.html' %}
-<div class="row">
-	<div class="col-md-12">
-		<form action="." method="post" class="form">
-		    {% csrf_token %}
-		    {% render_form form %}
-            <div class="form-group">
-                <div class="col-md-12 text-right">
-		            <button type="submit" class="btn btn-primary">Submit</button>
-		            {% if return_url %}
-                        <a href="{% url return_url %}" class="btn btn-default">Cancel</a>
-                    {% endif %}
-                </div>
-            </div>
-		</form>
-		<h4>CSV Format</h4>
-		<table class="table">
-			<thead>
-				<tr>
-					<th>Field</th>
-					<th>Description</th>
-					<th>Example</th>
-				</tr>
-			</thead>
-			<tbody>
-				<tr>
-					<td>Name</td>
-					<td>Device name (optional)</td>
-					<td>rack101_sw1</td>
-				</tr>
-				<tr>
-					<td>Device role</td>
-					<td>Functional role of device</td>
-					<td>ToR Switch</td>
-				</tr>
-				<tr>
-					<td>Tenant</td>
-					<td>Name of tenant (optional)</td>
-					<td>Pied Piper</td>
-				</tr>
-				<tr>
-					<td>Device manufacturer</td>
-					<td>Hardware manufacturer</td>
-					<td>Juniper</td>
-				</tr>
-				<tr>
-					<td>Device model</td>
-					<td>Hardware model</td>
-					<td>EX4300-48T</td>
-				</tr>
-				<tr>
-					<td>Platform</td>
-					<td>Software running on device (optional)</td>
-					<td>Juniper Junos</td>
-				</tr>
-				<tr>
-					<td>Serial number</td>
-					<td>Physical serial number (optional)</td>
-					<td>CAB00577291</td>
-				</tr>
-				<tr>
-					<td>Asset tag</td>
-					<td>Unique alphanumeric tag (optional)</td>
-					<td>ABC123456</td>
-				</tr>
-                <tr>
-                    <td>Status</td>
-                    <td>Current status</td>
-                    <td>Active</td>
-                </tr>
-				<tr>
-					<td>Site</td>
-					<td>Site name</td>
-					<td>Ashburn-VA</td>
-				</tr>
-				<tr>
-					<td>Rack</td>
-					<td>Rack name (optional)</td>
-					<td>R101</td>
-				</tr>
-				<tr>
-					<td>Position (U)</td>
-					<td>Lowest-numbered rack unit occupied by the device (optional)</td>
-					<td>21</td>
-				</tr>
-				<tr>
-					<td>Face</td>
-					<td>Rack face; front or rear (required if position is set)</td>
-					<td>Rear</td>
-				</tr>
-			</tbody>
-		</table>
-		<h4>Example</h4>
-		<pre>rack101_sw1,ToR Switch,Pied Piper,Juniper,EX4300-48T,Juniper Junos,CAB00577291,ABC123456,Active,Ashburn-VA,R101,21,Rear</pre>
-	</div>
-</div>
+{% block tabs %}
+    {% include 'dcim/inc/device_import_header.html' %}
 {% endblock %}

+ 3 - 91
netbox/templates/dcim/device_import_child.html

@@ -1,93 +1,5 @@
-{% extends '_base.html' %}
-{% load form_helpers %}
+{% extends 'utilities/obj_import.html' %}
 
-{% block title %}Device Import{% endblock %}
-
-{% block content %}
-{% include 'dcim/inc/device_import_header.html' with active_tab='child_import' %}
-<div class="row">
-	<div class="col-md-12">
-		<form action="." method="post" class="form">
-		    {% csrf_token %}
-		    {% render_form form %}
-            <div class="form-group">
-                <div class="col-md-12 text-right">
-		            <button type="submit" class="btn btn-primary">Submit</button>
-		            {% if return_url %}
-                        <a href="{% url return_url %}" class="btn btn-default">Cancel</a>
-                    {% endif %}
-                </div>
-            </div>
-		</form>
-		<h4>CSV Format</h4>
-		<table class="table">
-			<thead>
-				<tr>
-					<th>Field</th>
-					<th>Description</th>
-					<th>Example</th>
-				</tr>
-			</thead>
-			<tbody>
-				<tr>
-					<td>Name</td>
-					<td>Device name (optional)</td>
-					<td>Blade12</td>
-				</tr>
-				<tr>
-					<td>Device role</td>
-					<td>Functional role of device</td>
-					<td>Blade Server</td>
-				</tr>
-				<tr>
-					<td>Tenant</td>
-					<td>Name of tenant (optional)</td>
-					<td>Pied Piper</td>
-				</tr>
-				<tr>
-					<td>Device manufacturer</td>
-					<td>Hardware manufacturer</td>
-					<td>Dell</td>
-				</tr>
-				<tr>
-					<td>Device model</td>
-					<td>Hardware model</td>
-					<td>BS2000T</td>
-				</tr>
-				<tr>
-					<td>Platform</td>
-					<td>Software running on device (optional)</td>
-					<td>Linux</td>
-				</tr>
-				<tr>
-					<td>Serial number</td>
-					<td>Physical serial number (optional)</td>
-					<td>CAB00577291</td>
-				</tr>
-				<tr>
-					<td>Asset tag</td>
-					<td>Unique alphanumeric tag (optional)</td>
-					<td>ABC123456</td>
-				</tr>
-                <tr>
-                    <td>Status</td>
-                    <td>Current status</td>
-                    <td>Active</td>
-                </tr>
-				<tr>
-					<td>Parent device</td>
-					<td>Parent device</td>
-					<td>Server101</td>
-				</tr>
-				<tr>
-					<td>Device bay</td>
-					<td>Device bay name</td>
-					<td>Slot 4</td>
-				</tr>
-			</tbody>
-		</table>
-		<h4>Example</h4>
-		<pre>Blade12,Blade Server,Pied Piper,Dell,BS2000T,Linux,CAB00577291,ABC123456,Active,Server101,Slot4</pre>
-	</div>
-</div>
+{% block tabs %}
+    {% include 'dcim/inc/device_import_header.html' with active_tab='child_import' %}
 {% endblock %}

+ 0 - 1
netbox/templates/dcim/inc/device_import_header.html

@@ -1,4 +1,3 @@
-<h1>Device Import</h1>
 <ul class="nav nav-tabs" style="margin-bottom: 20px">
     <li role="presentation"{% if not active_tab %} class="active"{% endif %}><a href="{% url 'dcim:device_import' %}">Racked Devices</a></li>
     <li role="presentation"{% if active_tab == 'child_import' %} class="active"{% endif %}><a href="{% url 'dcim:device_import_child' %}">Child Devices</a></li>

+ 0 - 70
netbox/templates/dcim/rack_import.html

@@ -1,70 +0,0 @@
-{% extends 'utilities/obj_import.html' %}
-
-{% block title %}Rack Import{% endblock %}
-
-{% block instructions %}
-    <h4>CSV Format</h4>
-    <table class="table">
-        <thead>
-            <tr>
-                <th>Field</th>
-                <th>Description</th>
-                <th>Example</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr>
-                <td>Site</td>
-                <td>Name of the assigned site</td>
-                <td>DC-4</td>
-            </tr>
-            <tr>
-                <td>Group</td>
-                <td>Rack group name (optional)</td>
-                <td>Cage 1400</td>
-            </tr>
-            <tr>
-                <td>Name</td>
-                <td>Internal rack name</td>
-                <td>R101</td>
-            </tr>
-            <tr>
-                <td>Facility ID</td>
-                <td>Rack ID assigned by the facility (optional)</td>
-                <td>J12.100</td>
-            </tr>
-            <tr>
-                <td>Tenant</td>
-                <td>Name of tenant (optional)</td>
-                <td>Pied Piper</td>
-            </tr>
-            <tr>
-                <td>Role</td>
-                <td>Functional role (optional)</td>
-                <td>Compute</td>
-            </tr>
-            <tr>
-                <td>Type</td>
-                <td>Rack type (optional)</td>
-                <td>4-post cabinet</td>
-            </tr>
-            <tr>
-                <td>Width</td>
-                <td>Rail-to-rail width (19 or 23 inches)</td>
-                <td>19</td>
-            </tr>
-            <tr>
-                <td>Height</td>
-                <td>Height in rack units</td>
-                <td>42</td>
-            </tr>
-            <tr>
-                <td>Descending units</td>
-                <td>Units are numbered top-to-bottom</td>
-                <td>False</td>
-            </tr>
-        </tbody>
-    </table>
-    <h4>Example</h4>
-    <pre>DC-4,Cage 1400,R101,J12.100,Pied Piper,Compute,4-post cabinet,19,42,False</pre>
-{% endblock %}

+ 0 - 81
netbox/templates/dcim/site_import.html

@@ -1,81 +0,0 @@
-{% extends '_base.html' %}
-{% load form_helpers %}
-
-{% block title %}Site Import{% endblock %}
-
-{% block content %}
-<h1>Site Import</h1>
-<div class="row">
-	<div class="col-md-6">
-		<form action="." method="post" class="form">
-		    {% csrf_token %}
-		    {% render_form form %}
-		    <div class="form-group">
-		        <button type="submit" class="btn btn-primary">Submit</button>
-                <a href="{% url return_url %}" class="btn btn-default">Cancel</a>
-		    </div>
-		</form>
-	</div>
-	<div class="col-md-6">
-		<h4>CSV Format</h4>
-		<table class="table">
-			<thead>
-				<tr>
-					<th>Field</th>
-					<th>Description</th>
-					<th>Example</th>
-				</tr>
-			</thead>
-			<tbody>
-				<tr>
-					<td>Name</td>
-					<td>Site's proper name</td>
-					<td>ASH-4 South</td>
-				</tr>
-				<tr>
-					<td>Slug</td>
-					<td>URL-friendly name</td>
-					<td>ash4-south</td>
-				</tr>
-				<tr>
-					<td>Region</td>
-					<td>Name of region (optional)</td>
-					<td>North America</td>
-				</tr>
-				<tr>
-					<td>Tenant</td>
-					<td>Name of tenant (optional)</td>
-					<td>Pied Piper</td>
-				</tr>
-				<tr>
-					<td>Facility</td>
-					<td>Name of the hosting facility (optional)</td>
-					<td>Equinix DC6</td>
-				</tr>
-				<tr>
-					<td>ASN</td>
-					<td>Autonomous system number (optional)</td>
-					<td>65000</td>
-				</tr>
-				<tr>
-					<td>Contact Name</td>
-					<td>Name of administrative contact (optional)</td>
-					<td>Hank Hill</td>
-				</tr>
-				<tr>
-					<td>Contact Phone</td>
-					<td>Phone number (optional)</td>
-					<td>+1-214-555-1234</td>
-				</tr>
-				<tr>
-					<td>Contact E-mail</td>
-					<td>E-mail address (optional)</td>
-					<td>hhill@example.com</td>
-				</tr>
-			</tbody>
-		</table>
-		<h4>Example</h4>
-		<pre>ASH-4 South,ash4-south,North America,Pied Piper,Equinix DC6,65000,Hank Hill,+1-214-555-1234,hhill@example.com</pre>
-	</div>
-</div>
-{% endblock %}

+ 1 - 0
netbox/templates/utilities/obj_import.html

@@ -4,6 +4,7 @@
 
 {% block content %}
 <h1>{% block title %}{{ obj_type|bettertitle }} Import{% endblock %}</h1>
+{% block tabs %}{% endblock %}
 <div class="row">
 	<div class="col-md-6">
         {% if form.non_field_errors %}