Parcourir la source

Fixes #527: Support for nullifying custom fields during bulk editing

Jeremy Stretch il y a 8 ans
Parent
commit
73945899fe
3 fichiers modifiés avec 35 ajouts et 24 suppressions
  1. 13 10
      netbox/extras/forms.py
  2. 7 2
      netbox/utilities/forms.py
  3. 15 12
      netbox/utilities/views.py

+ 13 - 10
netbox/extras/forms.py

@@ -71,10 +71,10 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F
 
 
 class CustomFieldForm(forms.ModelForm):
-    custom_fields = []
 
     def __init__(self, *args, **kwargs):
 
+        self.custom_fields = []
         self.obj_type = ContentType.objects.get_for_model(self._meta.model)
 
         super(CustomFieldForm, self).__init__(*args, **kwargs)
@@ -125,21 +125,24 @@ class CustomFieldForm(forms.ModelForm):
 
 
 class CustomFieldBulkEditForm(BulkEditForm):
-    custom_fields = []
-
-    def __init__(self, model, *args, **kwargs):
-
-        self.obj_type = ContentType.objects.get_for_model(model)
 
+    def __init__(self, *args, **kwargs):
         super(CustomFieldBulkEditForm, self).__init__(*args, **kwargs)
 
+        self.custom_fields = []
+        self.obj_type = ContentType.objects.get_for_model(self.model)
+
         # Add all applicable CustomFields to the form
-        custom_fields = []
-        for name, field in get_custom_fields_for_model(self.obj_type, bulk_edit=True).items():
+        custom_fields = get_custom_fields_for_model(self.obj_type, bulk_edit=True).items()
+        for name, field in custom_fields:
+            # Annotate non-required custom fields as nullable
+            if not field.required:
+                self.nullable_fields.append(name)
             field.required = False
             self.fields[name] = field
-            custom_fields.append(name)
-        self.custom_fields = custom_fields
+            # Annotate this as a custom field
+            self.custom_fields.append(name)
+        print(self.nullable_fields)
 
 
 class CustomFieldFilterForm(forms.Form):

+ 7 - 2
netbox/utilities/forms.py

@@ -296,9 +296,14 @@ class ConfirmationForm(forms.Form, BootstrapMixin):
 
 class BulkEditForm(forms.Form):
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, model, *args, **kwargs):
         super(BulkEditForm, self).__init__(*args, **kwargs)
-        self.nullable_fields = getattr(self.Meta, 'nullable_fields')
+        self.model = model
+        # Copy any nullable fields defined in Meta
+        if hasattr(self.Meta, 'nullable_fields'):
+            self.nullable_fields = [field for field in self.Meta.nullable_fields]
+        else:
+            self.nullable_fields = []
 
 
 class BulkImportForm(forms.Form):

+ 15 - 12
netbox/utilities/views.py

@@ -301,10 +301,7 @@ class BulkEditView(View):
             pk_list = [int(pk) for pk in request.POST.getlist('pk')]
 
         if '_apply' in request.POST:
-            if hasattr(self.form, 'custom_fields'):
-                form = self.form(self.cls, request.POST)
-            else:
-                form = self.form(request.POST)
+            form = self.form(self.cls, request.POST)
             if form.is_valid():
 
                 custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else []
@@ -322,7 +319,7 @@ class BulkEditView(View):
 
                 # Update custom fields for objects
                 if custom_fields:
-                    objs_updated = self.update_custom_fields(pk_list, form, custom_fields)
+                    objs_updated = self.update_custom_fields(pk_list, form, custom_fields, nullified_fields)
                     if objs_updated and not updated_count:
                         updated_count = objs_updated
 
@@ -333,10 +330,7 @@ class BulkEditView(View):
                 return redirect(redirect_url)
 
         else:
-            if hasattr(self.form, 'custom_fields'):
-                form = self.form(self.cls, initial={'pk': pk_list})
-            else:
-                form = self.form(initial={'pk': pk_list})
+            form = self.form(self.cls, initial={'pk': pk_list})
 
         selected_objects = self.cls.objects.filter(pk__in=pk_list)
         if not selected_objects:
@@ -349,14 +343,23 @@ class BulkEditView(View):
             'cancel_url': redirect_url,
         })
 
-    def update_custom_fields(self, pk_list, form, fields):
+    def update_custom_fields(self, pk_list, form, fields, nullified_fields):
         obj_type = ContentType.objects.get_for_model(self.cls)
         objs_updated = False
 
         for name in fields:
-            if form.cleaned_data[name] not in [None, u'']:
 
-                field = form.fields[name].model
+            field = form.fields[name].model
+
+            # Setting the field to null
+            if name in form.nullable_fields and name in nullified_fields:
+
+                # Delete all CustomFieldValues for instances of this field belonging to the selected objects.
+                CustomFieldValue.objects.filter(field=field, obj_type=obj_type, obj_id__in=pk_list).delete()
+                objs_updated = True
+
+            # Updating the value of the field
+            elif form.cleaned_data[name] not in [None, u'']:
 
                 # Check for zero value (bulk editing)
                 if isinstance(form.fields[name], TypedChoiceField) and form.cleaned_data[name] == 0: