mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-25 01:48:38 -06:00
Fixes #527: Support for nullifying custom fields during bulk editing
This commit is contained in:
parent
8227a9ff9c
commit
73945899fe
@ -71,10 +71,10 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F
|
|||||||
|
|
||||||
|
|
||||||
class CustomFieldForm(forms.ModelForm):
|
class CustomFieldForm(forms.ModelForm):
|
||||||
custom_fields = []
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
|
self.custom_fields = []
|
||||||
self.obj_type = ContentType.objects.get_for_model(self._meta.model)
|
self.obj_type = ContentType.objects.get_for_model(self._meta.model)
|
||||||
|
|
||||||
super(CustomFieldForm, self).__init__(*args, **kwargs)
|
super(CustomFieldForm, self).__init__(*args, **kwargs)
|
||||||
@ -125,21 +125,24 @@ class CustomFieldForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class CustomFieldBulkEditForm(BulkEditForm):
|
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)
|
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
|
# Add all applicable CustomFields to the form
|
||||||
custom_fields = []
|
custom_fields = get_custom_fields_for_model(self.obj_type, bulk_edit=True).items()
|
||||||
for name, field in 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
|
field.required = False
|
||||||
self.fields[name] = field
|
self.fields[name] = field
|
||||||
custom_fields.append(name)
|
# Annotate this as a custom field
|
||||||
self.custom_fields = custom_fields
|
self.custom_fields.append(name)
|
||||||
|
print(self.nullable_fields)
|
||||||
|
|
||||||
|
|
||||||
class CustomFieldFilterForm(forms.Form):
|
class CustomFieldFilterForm(forms.Form):
|
||||||
|
@ -296,9 +296,14 @@ class ConfirmationForm(forms.Form, BootstrapMixin):
|
|||||||
|
|
||||||
class BulkEditForm(forms.Form):
|
class BulkEditForm(forms.Form):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, model, *args, **kwargs):
|
||||||
super(BulkEditForm, self).__init__(*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):
|
class BulkImportForm(forms.Form):
|
||||||
|
@ -301,10 +301,7 @@ class BulkEditView(View):
|
|||||||
pk_list = [int(pk) for pk in 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'):
|
form = self.form(self.cls, request.POST)
|
||||||
form = self.form(self.cls, request.POST)
|
|
||||||
else:
|
|
||||||
form = self.form(request.POST)
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
|
||||||
custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else []
|
custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else []
|
||||||
@ -322,7 +319,7 @@ class BulkEditView(View):
|
|||||||
|
|
||||||
# Update custom fields for objects
|
# Update custom fields for objects
|
||||||
if custom_fields:
|
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:
|
if objs_updated and not updated_count:
|
||||||
updated_count = objs_updated
|
updated_count = objs_updated
|
||||||
|
|
||||||
@ -333,10 +330,7 @@ class BulkEditView(View):
|
|||||||
return redirect(redirect_url)
|
return redirect(redirect_url)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if hasattr(self.form, 'custom_fields'):
|
form = self.form(self.cls, initial={'pk': pk_list})
|
||||||
form = self.form(self.cls, initial={'pk': pk_list})
|
|
||||||
else:
|
|
||||||
form = self.form(initial={'pk': pk_list})
|
|
||||||
|
|
||||||
selected_objects = self.cls.objects.filter(pk__in=pk_list)
|
selected_objects = self.cls.objects.filter(pk__in=pk_list)
|
||||||
if not selected_objects:
|
if not selected_objects:
|
||||||
@ -349,14 +343,23 @@ class BulkEditView(View):
|
|||||||
'cancel_url': redirect_url,
|
'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)
|
obj_type = ContentType.objects.get_for_model(self.cls)
|
||||||
objs_updated = False
|
objs_updated = False
|
||||||
|
|
||||||
for name in fields:
|
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)
|
# Check for zero value (bulk editing)
|
||||||
if isinstance(form.fields[name], TypedChoiceField) and form.cleaned_data[name] == 0:
|
if isinstance(form.fields[name], TypedChoiceField) and form.cleaned_data[name] == 0:
|
||||||
|
Loading…
Reference in New Issue
Block a user