Parcourir la source

Closes #1084: Include custom fields when creating IP addresses in bulk

Jeremy Stretch il y a 8 ans
Parent
commit
401357b8cb

+ 8 - 5
netbox/ipam/forms.py

@@ -418,12 +418,15 @@ class IPAddressForm(BootstrapMixin, ReturnURLForm, CustomFieldForm):
                 self.fields['nat_inside'].choices = []
 
 
-class IPAddressBulkAddForm(BootstrapMixin, forms.Form):
-    address = ExpandableIPAddressField()
+class IPAddressBulkAddForm(BootstrapMixin, CustomFieldForm):
+    address_pattern = ExpandableIPAddressField(label='Address Pattern')
     vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, label='VRF', empty_label='Global')
-    tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
-    status = forms.ChoiceField(choices=IPADDRESS_STATUS_CHOICES)
-    description = forms.CharField(max_length=100, required=False)
+
+    pattern_map = ('address_pattern', 'address')
+
+    class Meta:
+        model = IPAddress
+        fields = ['address_pattern', 'vrf', 'tenant', 'status', 'description']
 
 
 class IPAddressAssignForm(BootstrapMixin, forms.Form):

+ 1 - 1
netbox/ipam/views.py

@@ -588,7 +588,7 @@ class IPAddressDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class IPAddressBulkAddView(PermissionRequiredMixin, BulkAddView):
     permission_required = 'ipam.add_ipaddress'
     form = forms.IPAddressBulkAddForm
-    model = IPAddress
+    model_form = forms.IPAddressForm
     template_name = 'ipam/ipaddress_bulk_add.html'
     default_return_url = 'ipam:ipaddress_list'
 

+ 10 - 2
netbox/templates/ipam/ipaddress_bulk_add.html

@@ -10,13 +10,21 @@
 
 {% block form %}
     <div class="panel panel-default">
-        <div class="panel-heading"><strong>IP Address</strong></div>
+        <div class="panel-heading"><strong>IP Addresses</strong></div>
         <div class="panel-body">
-            {% render_field form.address %}
+            {% render_field form.address_pattern %}
             {% render_field form.vrf %}
             {% render_field form.tenant %}
             {% render_field form.status %}
             {% render_field form.description %}
         </div>
     </div>
+    {% if form.custom_fields %}
+        <div class="panel panel-default">
+            <div class="panel-heading"><strong>Custom Fields</strong></div>
+            <div class="panel-body">
+                {% render_custom_fields form %}
+            </div>
+        </div>
+    {% endif %}
 {% endblock %}

+ 13 - 16
netbox/utilities/views.py

@@ -296,12 +296,12 @@ class BulkAddView(View):
     Create new objects in bulk.
 
     form: Form class
-    model: The model of the objects being created
+    model_form: The ModelForm used to create individual objects
     template_name: The name of the template
     default_return_url: Name of the URL to which the user is redirected after creating the objects
     """
     form = None
-    model = None
+    model_form = None
     template_name = None
     default_return_url = 'home'
 
@@ -310,47 +310,44 @@ class BulkAddView(View):
         form = self.form()
 
         return render(request, self.template_name, {
-            'obj_type': self.model._meta.verbose_name,
+            'obj_type': self.model_form._meta.model._meta.verbose_name,
             'form': form,
             'return_url': reverse(self.default_return_url),
         })
 
     def post(self, request):
 
+        model = self.model_form._meta.model
         form = self.form(request.POST)
         if form.is_valid():
 
-            # The first field will be used as the pattern
-            field_names = list(form.fields.keys())
-            pattern_field = field_names[0]
+            # Read the pattern field and target from the form's pattern_map
+            pattern_field, pattern_target = form.pattern_map
             pattern = form.cleaned_data[pattern_field]
-
-            # All other fields will be copied as object attributes
-            kwargs = {k: form.cleaned_data[k] for k in field_names[1:]}
+            model_form_data = form.cleaned_data
 
             new_objs = []
             try:
                 with transaction.atomic():
                     for value in pattern:
-                        obj = self.model(**kwargs)
-                        setattr(obj, pattern_field, value)
-                        obj.full_clean()
-                        obj.save()
+                        model_form_data[pattern_target] = value
+                        model_form = self.model_form(model_form_data)
+                        obj = model_form.save()
                         new_objs.append(obj)
             except ValidationError as e:
                 form.add_error(None, e)
 
             if not form.errors:
-                msg = u"Added {} {}".format(len(new_objs), self.model._meta.verbose_name_plural)
+                msg = u"Added {} {}".format(len(new_objs), model._meta.verbose_name_plural)
                 messages.success(request, msg)
-                UserAction.objects.log_bulk_create(request.user, ContentType.objects.get_for_model(self.model), msg)
+                UserAction.objects.log_bulk_create(request.user, ContentType.objects.get_for_model(model), msg)
                 if '_addanother' in request.POST:
                     return redirect(request.path)
                 return redirect(self.default_return_url)
 
         return render(request, self.template_name, {
             'form': form,
-            'obj_type': self.model._meta.verbose_name,
+            'obj_type': model._meta.verbose_name,
             'return_url': reverse(self.default_return_url),
         })