mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-25 01:48:38 -06:00
Closes #1110: Expand bulk edit forms to include boolean fields (e.g. toggle is_pool for prefixes)
This commit is contained in:
parent
e7a6d1f532
commit
aea5612c39
@ -11,9 +11,9 @@ from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFi
|
|||||||
from ipam.models import IPAddress
|
from ipam.models import IPAddress
|
||||||
from tenancy.models import Tenant
|
from tenancy.models import Tenant
|
||||||
from utilities.forms import (
|
from utilities.forms import (
|
||||||
APISelect, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, BulkImportForm, CommentField,
|
APISelect, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
|
||||||
CSVDataField, ExpandableNameField, FilterChoiceField, FlexibleModelChoiceField, Livesearch, SelectWithDisabled,
|
BulkImportForm, CommentField, CSVDataField, ExpandableNameField, FilterChoiceField, FlexibleModelChoiceField,
|
||||||
SmallTextarea, SlugField, FilterTreeNodeMultipleChoiceField,
|
Livesearch, SelectWithDisabled, SmallTextarea, SlugField, FilterTreeNodeMultipleChoiceField,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .formfields import MACAddressFormField
|
from .formfields import MACAddressFormField
|
||||||
@ -272,6 +272,7 @@ class RackBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
|||||||
type = forms.ChoiceField(choices=add_blank_choice(RACK_TYPE_CHOICES), required=False, label='Type')
|
type = forms.ChoiceField(choices=add_blank_choice(RACK_TYPE_CHOICES), required=False, label='Type')
|
||||||
width = forms.ChoiceField(choices=add_blank_choice(RACK_WIDTH_CHOICES), required=False, label='Width')
|
width = forms.ChoiceField(choices=add_blank_choice(RACK_WIDTH_CHOICES), required=False, label='Width')
|
||||||
u_height = forms.IntegerField(required=False, label='Height (U)')
|
u_height = forms.IntegerField(required=False, label='Height (U)')
|
||||||
|
desc_units = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label='Descending units')
|
||||||
comments = CommentField(widget=SmallTextarea)
|
comments = CommentField(widget=SmallTextarea)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -375,7 +376,13 @@ class DeviceTypeBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
|||||||
pk = forms.ModelMultipleChoiceField(queryset=DeviceType.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(queryset=DeviceType.objects.all(), widget=forms.MultipleHiddenInput)
|
||||||
manufacturer = forms.ModelChoiceField(queryset=Manufacturer.objects.all(), required=False)
|
manufacturer = forms.ModelChoiceField(queryset=Manufacturer.objects.all(), required=False)
|
||||||
u_height = forms.IntegerField(min_value=1, required=False)
|
u_height = forms.IntegerField(min_value=1, required=False)
|
||||||
|
is_full_depth = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label='Is full depth')
|
||||||
interface_ordering = forms.ChoiceField(choices=add_blank_choice(IFACE_ORDERING_CHOICES), required=False)
|
interface_ordering = forms.ChoiceField(choices=add_blank_choice(IFACE_ORDERING_CHOICES), required=False)
|
||||||
|
is_console_server = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label='Is full depth')
|
||||||
|
is_pdu = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label='Is a PDU')
|
||||||
|
is_network_device = forms.NullBooleanField(
|
||||||
|
required=False, widget=BulkEditNullBooleanSelect, label='Is a network device'
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = []
|
nullable_fields = []
|
||||||
@ -484,6 +491,7 @@ class InterfaceTemplateCreateForm(DeviceComponentForm):
|
|||||||
class InterfaceTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
|
class InterfaceTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=InterfaceTemplate.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(queryset=InterfaceTemplate.objects.all(), widget=forms.MultipleHiddenInput)
|
||||||
form_factor = forms.ChoiceField(choices=add_blank_choice(IFACE_FF_CHOICES), required=False)
|
form_factor = forms.ChoiceField(choices=add_blank_choice(IFACE_FF_CHOICES), required=False)
|
||||||
|
mgmt_only = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label='Management only')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = []
|
nullable_fields = []
|
||||||
@ -1413,6 +1421,7 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
|
|||||||
device = forms.ModelChoiceField(queryset=Device.objects.all(), widget=forms.HiddenInput)
|
device = forms.ModelChoiceField(queryset=Device.objects.all(), widget=forms.HiddenInput)
|
||||||
lag = forms.ModelChoiceField(queryset=Interface.objects.all(), required=False, label='Parent LAG')
|
lag = forms.ModelChoiceField(queryset=Interface.objects.all(), required=False, label='Parent LAG')
|
||||||
form_factor = forms.ChoiceField(choices=add_blank_choice(IFACE_FF_CHOICES), required=False)
|
form_factor = forms.ChoiceField(choices=add_blank_choice(IFACE_FF_CHOICES), required=False)
|
||||||
|
mgmt_only = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label='Management only')
|
||||||
description = forms.CharField(max_length=100, required=False)
|
description = forms.CharField(max_length=100, required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -5,8 +5,8 @@ from dcim.models import Site, Rack, Device, Interface
|
|||||||
from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
|
from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
|
||||||
from tenancy.models import Tenant
|
from tenancy.models import Tenant
|
||||||
from utilities.forms import (
|
from utilities.forms import (
|
||||||
APISelect, BootstrapMixin, BulkImportForm, CSVDataField, ExpandableIPAddressField, FilterChoiceField, Livesearch,
|
APISelect, BootstrapMixin, BulkEditNullBooleanSelect, BulkImportForm, CSVDataField, ExpandableIPAddressField,
|
||||||
ReturnURLForm, SlugField, add_blank_choice,
|
FilterChoiceField, Livesearch, ReturnURLForm, SlugField, add_blank_choice,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
@ -61,6 +61,9 @@ class VRFImportForm(BootstrapMixin, BulkImportForm):
|
|||||||
class VRFBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
class VRFBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=VRF.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(queryset=VRF.objects.all(), widget=forms.MultipleHiddenInput)
|
||||||
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
||||||
|
enforce_unique = forms.NullBooleanField(
|
||||||
|
required=False, widget=BulkEditNullBooleanSelect, label='Enforce unique space'
|
||||||
|
)
|
||||||
description = forms.CharField(max_length=100, required=False)
|
description = forms.CharField(max_length=100, required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -256,6 +259,7 @@ class PrefixBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
|||||||
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
||||||
status = forms.ChoiceField(choices=add_blank_choice(PREFIX_STATUS_CHOICES), required=False)
|
status = forms.ChoiceField(choices=add_blank_choice(PREFIX_STATUS_CHOICES), required=False)
|
||||||
role = forms.ModelChoiceField(queryset=Role.objects.all(), required=False)
|
role = forms.ModelChoiceField(queryset=Role.objects.all(), required=False)
|
||||||
|
is_pool = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label='Is a pool')
|
||||||
description = forms.CharField(max_length=100, required=False)
|
description = forms.CharField(max_length=100, required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -138,6 +138,19 @@ class ColorSelect(forms.Select):
|
|||||||
option_value, selected_html, option_value, force_text(option_label))
|
option_value, selected_html, option_value, force_text(option_label))
|
||||||
|
|
||||||
|
|
||||||
|
class BulkEditNullBooleanSelect(forms.NullBooleanSelect):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(BulkEditNullBooleanSelect, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# Override the built-in choice labels
|
||||||
|
self.choices = (
|
||||||
|
('1', '---------'),
|
||||||
|
('2', 'Yes'),
|
||||||
|
('3', 'No'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SelectWithDisabled(forms.Select):
|
class SelectWithDisabled(forms.Select):
|
||||||
"""
|
"""
|
||||||
Modified the stock Select widget to accept choices using a dict() for a label. The dict for each option must include
|
Modified the stock Select widget to accept choices using a dict() for a label. The dict for each option must include
|
||||||
|
@ -423,7 +423,7 @@ class BulkEditView(View):
|
|||||||
filter: FilterSet to apply when deleting by QuerySet
|
filter: FilterSet to apply when deleting by QuerySet
|
||||||
form: The form class used to edit objects in bulk
|
form: The form class used to edit objects in bulk
|
||||||
template_name: The name of the template
|
template_name: The name of the template
|
||||||
default_return_url: Name of the URL to which the user is redirected after editing the objects (can be overriden by
|
default_return_url: Name of the URL to which the user is redirected after editing the objects (can be overridden by
|
||||||
POSTing return_url)
|
POSTing return_url)
|
||||||
"""
|
"""
|
||||||
cls = None
|
cls = None
|
||||||
@ -475,7 +475,7 @@ class BulkEditView(View):
|
|||||||
fields_to_update[field] = ''
|
fields_to_update[field] = ''
|
||||||
else:
|
else:
|
||||||
fields_to_update[field] = None
|
fields_to_update[field] = None
|
||||||
elif form.cleaned_data[field]:
|
elif form.cleaned_data[field] not in (None, ''):
|
||||||
fields_to_update[field] = form.cleaned_data[field]
|
fields_to_update[field] = form.cleaned_data[field]
|
||||||
updated_count = self.cls.objects.filter(pk__in=pk_list).update(**fields_to_update)
|
updated_count = self.cls.objects.filter(pk__in=pk_list).update(**fields_to_update)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user