From 9bdb50c33e181e71c649f8d77a668830fd6eb12b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 17 Aug 2016 15:52:27 -0400 Subject: [PATCH] Optimized bulk editing of custom fields --- netbox/extras/forms.py | 25 +++++++++++++------------ netbox/extras/models.py | 6 +++--- netbox/utilities/views.py | 30 +++++++++++++++++++----------- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index 55fef2995..20b52589d 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -81,18 +81,19 @@ class CustomFieldForm(forms.ModelForm): def _save_custom_fields(self): 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): obj = super(CustomFieldForm, self).save(commit) diff --git a/netbox/extras/models.py b/netbox/extras/models.py index 06f6ba5af..0a038e657 100644 --- a/netbox/extras/models.py +++ b/netbox/extras/models.py @@ -155,9 +155,9 @@ class CustomFieldValue(models.Model): self.serialized_value = self.field.serialize_value(value) 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: super(CustomFieldValue, self).save(*args, **kwargs) diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 03b24c7ab..19643e664 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -277,9 +277,9 @@ class BulkEditView(View): redirect_url = reverse(self.default_redirect_url) 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: - pk_list = request.POST.getlist('pk') + pk_list = [int(pk) for pk in request.POST.getlist('pk')] if '_apply' in request.POST: if hasattr(self.form, 'custom_fields'): @@ -334,17 +334,25 @@ class BulkEditView(View): def update_custom_fields(self, pk_list, form, fields): obj_type = ContentType.objects.get_for_model(self.cls) - for name in fields: 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):