Browse Source

Optimized bulk editing of custom fields

Jeremy Stretch 8 years ago
parent
commit
9bdb50c33e
3 changed files with 35 additions and 26 deletions
  1. 13 12
      netbox/extras/forms.py
  2. 3 3
      netbox/extras/models.py
  3. 19 11
      netbox/utilities/views.py

+ 13 - 12
netbox/extras/forms.py

@@ -81,18 +81,19 @@ class CustomFieldForm(forms.ModelForm):
     def _save_custom_fields(self):
     def _save_custom_fields(self):
 
 
         for field_name in self.custom_fields:
         for field_name in self.custom_fields:
-            try:
-                cfv = CustomFieldValue.objects.select_related('field').get(field=self.fields[field_name].model,
-                                                                           obj_type=self.obj_type,
-                                                                           obj_id=self.instance.pk)
-            except CustomFieldValue.DoesNotExist:
-                cfv = CustomFieldValue(
-                    field=self.fields[field_name].model,
-                    obj_type=self.obj_type,
-                    obj_id=self.instance.pk
-                )
-            cfv.value = self.cleaned_data[field_name]
-            cfv.save()
+            if self.cleaned_data[field_name] not in [None, u'']:
+                try:
+                    cfv = CustomFieldValue.objects.select_related('field').get(field=self.fields[field_name].model,
+                                                                               obj_type=self.obj_type,
+                                                                               obj_id=self.instance.pk)
+                except CustomFieldValue.DoesNotExist:
+                    cfv = CustomFieldValue(
+                        field=self.fields[field_name].model,
+                        obj_type=self.obj_type,
+                        obj_id=self.instance.pk
+                    )
+                cfv.value = self.cleaned_data[field_name]
+                cfv.save()
 
 
     def save(self, commit=True):
     def save(self, commit=True):
         obj = super(CustomFieldForm, self).save(commit)
         obj = super(CustomFieldForm, self).save(commit)

+ 3 - 3
netbox/extras/models.py

@@ -155,9 +155,9 @@ class CustomFieldValue(models.Model):
         self.serialized_value = self.field.serialize_value(value)
         self.serialized_value = self.field.serialize_value(value)
 
 
     def save(self, *args, **kwargs):
     def save(self, *args, **kwargs):
-        if (self.field.type == CF_TYPE_TEXT and self.value == '') or self.value is None:
-            if self.pk:
-                self.delete()
+        # Delete this object if it no longer has a value to store
+        if self.pk and self.value is None:
+            self.delete()
         else:
         else:
             super(CustomFieldValue, self).save(*args, **kwargs)
             super(CustomFieldValue, self).save(*args, **kwargs)
 
 

+ 19 - 11
netbox/utilities/views.py

@@ -277,9 +277,9 @@ class BulkEditView(View):
             redirect_url = reverse(self.default_redirect_url)
             redirect_url = reverse(self.default_redirect_url)
 
 
         if request.POST.get('_all'):
         if request.POST.get('_all'):
-            pk_list = [x for x in request.POST.get('pk_all').split(',') if x]
+            pk_list = [int(pk) for pk in request.POST.get('pk_all').split(',') if pk]
         else:
         else:
-            pk_list = request.POST.getlist('pk')
+            pk_list = [int(pk) for pk in request.POST.getlist('pk')]
 
 
         if '_apply' in request.POST:
         if '_apply' in request.POST:
             if hasattr(self.form, 'custom_fields'):
             if hasattr(self.form, 'custom_fields'):
@@ -334,17 +334,25 @@ class BulkEditView(View):
 
 
     def update_custom_fields(self, pk_list, form, fields):
     def update_custom_fields(self, pk_list, form, fields):
         obj_type = ContentType.objects.get_for_model(self.cls)
         obj_type = ContentType.objects.get_for_model(self.cls)
-
         for name in fields:
         for name in fields:
             if form.cleaned_data[name] not in [None, u'']:
             if form.cleaned_data[name] not in [None, u'']:
-                for pk in pk_list:
-                    try:
-                        cfv = CustomFieldValue.objects.select_related('field').get(field=form.fields[name].model,
-                                                                                   obj_type=obj_type, obj_id=pk)
-                    except CustomFieldValue.DoesNotExist:
-                        cfv = CustomFieldValue(field=form.fields[name].model, obj_type=obj_type, obj_id=pk)
-                    cfv.value = form.cleaned_data[name]
-                    cfv.save()
+
+                field = form.fields[name].model
+                serialized_value = field.serialize_value(form.cleaned_data[name])
+                existing_cfvs = CustomFieldValue.objects.filter(field=field, obj_type=obj_type, obj_id__in=pk_list)
+
+                # Determine which objects have an existing CFV to update and which need a new CFV created.
+                update_list = [cfv['obj_id'] for cfv in existing_cfvs.values()]
+                create_list = list(set(pk_list) - set(update_list))
+
+                # Update any existing CFVs.
+                existing_cfvs.update(serialized_value=serialized_value)
+
+                # Create new CFVs as needed.
+                CustomFieldValue.objects.bulk_create([
+                    CustomFieldValue(field=field, obj_type=obj_type, obj_id=pk, serialized_value=serialized_value)
+                    for pk in create_list
+                ])
 
 
 
 
 class BulkDeleteView(View):
 class BulkDeleteView(View):