Răsfoiți Sursa

Allow import/export of regions (#1347)

Faidon Liambotis 8 ani în urmă
părinte
comite
fbc5e74318

+ 22 - 0
netbox/dcim/forms.py

@@ -70,6 +70,28 @@ class RegionForm(BootstrapMixin, forms.ModelForm):
         fields = ['parent', 'name', 'slug']
 
 
+class RegionCSVForm(forms.ModelForm):
+    parent = forms.ModelChoiceField(
+        queryset=Region.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of parent region',
+        error_messages={
+            'invalid_choice': 'Region not found.',
+        }
+    )
+
+    class Meta:
+        model = Region
+        fields = [
+            'name', 'slug', 'parent',
+        ]
+        help_texts = {
+            'name': 'Region name',
+            'slug': 'URL-friendly slug',
+        }
+
+
 #
 # Sites
 #

+ 11 - 0
netbox/dcim/models.py

@@ -43,6 +43,10 @@ class Region(MPTTModel):
     name = models.CharField(max_length=50, unique=True)
     slug = models.SlugField(unique=True)
 
+    csv_headers = [
+        'name', 'slug', 'parent',
+    ]
+
     class MPTTMeta:
         order_insertion_by = ['name']
 
@@ -52,6 +56,13 @@ class Region(MPTTModel):
     def get_absolute_url(self):
         return "{}?region={}".format(reverse('dcim:site_list'), self.slug)
 
+    def to_csv(self):
+        return csv_format([
+            self.name,
+            self.slug,
+            self.parent.name if self.parent else None,
+        ])
+
 
 #
 # Sites

+ 1 - 0
netbox/dcim/urls.py

@@ -15,6 +15,7 @@ urlpatterns = [
     # Regions
     url(r'^regions/$', views.RegionListView.as_view(), name='region_list'),
     url(r'^regions/add/$', views.RegionCreateView.as_view(), name='region_add'),
+    url(r'^regions/import/$', views.RegionBulkImportView.as_view(), name='region_import'),
     url(r'^regions/delete/$', views.RegionBulkDeleteView.as_view(), name='region_bulk_delete'),
     url(r'^regions/(?P<pk>\d+)/edit/$', views.RegionEditView.as_view(), name='region_edit'),
 

+ 7 - 0
netbox/dcim/views.py

@@ -202,6 +202,13 @@ class RegionEditView(RegionCreateView):
     permission_required = 'dcim.change_region'
 
 
+class RegionBulkImportView(PermissionRequiredMixin, BulkImportView):
+    permission_required = 'dcim.add_region'
+    model_form = forms.RegionCSVForm
+    table = tables.RegionTable
+    default_return_url = 'dcim:region_list'
+
+
 class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     permission_required = 'dcim.delete_region'
     cls = Region

+ 2 - 1
netbox/extras/constants.py

@@ -37,7 +37,8 @@ GRAPH_TYPE_CHOICES = (
 
 # Models which support export templates
 EXPORTTEMPLATE_MODELS = [
-    'site', 'rack', 'device', 'consoleport', 'powerport', 'interfaceconnection',    # DCIM
+    'site', 'region', 'rack', 'device',                                             # DCIM
+    'consoleport', 'powerport', 'interfaceconnection',                              # DCIM
     'aggregate', 'prefix', 'ipaddress', 'vlan',                                     # IPAM
     'provider', 'circuit',                                                          # Circuits
     'tenant',                                                                       # Tenants

+ 1 - 0
netbox/templates/_base.html

@@ -40,6 +40,7 @@
                             <li><a href="{% url 'dcim:region_list' %}"><i class="fa fa-search" aria-hidden="true"></i> Regions</a></li>
                             {% if perms.dcim.add_region %}
                                 <li><a href="{% url 'dcim:region_add' %}"><i class="fa fa-plus" aria-hidden="true"></i> Add a Region</a></li>
+                                <li><a href="{% url 'dcim:region_import' %}"><i class="fa fa-download" aria-hidden="true"></i> Import Regions</a></li>
                             {% endif %}
                             <li class="divider"></li>
                             <li><a href="{% url 'tenancy:tenant_list' %}"><i class="fa fa-search" aria-hidden="true"></i> Tenants</a></li>

+ 5 - 0
netbox/templates/dcim/region_list.html

@@ -10,7 +10,12 @@
             <span class="fa fa-plus" aria-hidden="true"></span>
             Add a region
         </a>
+        <a href="{% url 'dcim:region_import' %}" class="btn btn-info">
+            <span class="fa fa-download" aria-hidden="true"></span>
+            Import regions
+        </a>
     {% endif %}
+    {% include 'inc/export_button.html' with obj_type='regions' %}
 </div>
 <h1>{{ block.title }}</h1>
 <div class="row">