Просмотр исходного кода

Added bulk tag addition/removal

Jeremy Stretch 7 лет назад
Родитель
Сommit
208409110f

+ 3 - 3
netbox/circuits/forms.py

@@ -5,7 +5,7 @@ from django.db.models import Count
 from taggit.forms import TagField
 from taggit.forms import TagField
 
 
 from dcim.models import Site, Device, Interface, Rack
 from dcim.models import Site, Device, Interface, Rack
-from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
+from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
 from tenancy.forms import TenancyForm
 from tenancy.forms import TenancyForm
 from tenancy.models import Tenant
 from tenancy.models import Tenant
 from utilities.forms import (
 from utilities.forms import (
@@ -55,7 +55,7 @@ class ProviderCSVForm(forms.ModelForm):
         }
         }
 
 
 
 
-class ProviderBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class ProviderBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Provider.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=Provider.objects.all(), widget=forms.MultipleHiddenInput)
     asn = forms.IntegerField(required=False, label='ASN')
     asn = forms.IntegerField(required=False, label='ASN')
     account = forms.CharField(max_length=30, required=False, label='Account number')
     account = forms.CharField(max_length=30, required=False, label='Account number')
@@ -158,7 +158,7 @@ class CircuitCSVForm(forms.ModelForm):
         ]
         ]
 
 
 
 
-class CircuitBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Circuit.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=Circuit.objects.all(), widget=forms.MultipleHiddenInput)
     type = forms.ModelChoiceField(queryset=CircuitType.objects.all(), required=False)
     type = forms.ModelChoiceField(queryset=CircuitType.objects.all(), required=False)
     provider = forms.ModelChoiceField(queryset=Provider.objects.all(), required=False)
     provider = forms.ModelChoiceField(queryset=Provider.objects.all(), required=False)

+ 5 - 5
netbox/dcim/forms.py

@@ -10,7 +10,7 @@ from mptt.forms import TreeNodeChoiceField
 from taggit.forms import TagField
 from taggit.forms import TagField
 from timezone_field import TimeZoneFormField
 from timezone_field import TimeZoneFormField
 
 
-from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
+from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
 from ipam.models import IPAddress, VLAN, VLANGroup
 from ipam.models import IPAddress, VLAN, VLANGroup
 from tenancy.forms import TenancyForm
 from tenancy.forms import TenancyForm
 from tenancy.models import Tenant
 from tenancy.models import Tenant
@@ -170,7 +170,7 @@ class SiteCSVForm(forms.ModelForm):
         }
         }
 
 
 
 
-class SiteBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class SiteBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(
     pk = forms.ModelMultipleChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         widget=forms.MultipleHiddenInput
         widget=forms.MultipleHiddenInput
@@ -403,7 +403,7 @@ class RackCSVForm(forms.ModelForm):
                 )
                 )
 
 
 
 
-class RackBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Rack.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=Rack.objects.all(), widget=forms.MultipleHiddenInput)
     site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, label='Site')
     site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, label='Site')
     group = forms.ModelChoiceField(queryset=RackGroup.objects.all(), required=False, label='Group')
     group = forms.ModelChoiceField(queryset=RackGroup.objects.all(), required=False, label='Group')
@@ -572,7 +572,7 @@ class DeviceTypeCSVForm(forms.ModelForm):
         }
         }
 
 
 
 
-class DeviceTypeBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class DeviceTypeBulkEditForm(BootstrapMixin, AddRemoveTagsForm, 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)
@@ -1090,7 +1090,7 @@ class ChildDeviceCSVForm(BaseDeviceCSVForm):
                 raise forms.ValidationError("Parent device/bay ({} {}) not found".format(parent, device_bay_name))
                 raise forms.ValidationError("Parent device/bay ({} {}) not found".format(parent, device_bay_name))
 
 
 
 
-class DeviceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Device.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=Device.objects.all(), widget=forms.MultipleHiddenInput)
     device_type = forms.ModelChoiceField(queryset=DeviceType.objects.all(), required=False, label='Type')
     device_type = forms.ModelChoiceField(queryset=DeviceType.objects.all(), required=False, label='Type')
     device_role = forms.ModelChoiceField(queryset=DeviceRole.objects.all(), required=False, label='Role')
     device_role = forms.ModelChoiceField(queryset=DeviceRole.objects.all(), required=False, label='Role')

+ 11 - 0
netbox/extras/forms.py

@@ -7,6 +7,7 @@ from django.contrib.auth.models import User
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ObjectDoesNotExist
 from django.core.exceptions import ObjectDoesNotExist
 from mptt.forms import TreeNodeMultipleChoiceField
 from mptt.forms import TreeNodeMultipleChoiceField
+from taggit.forms import TagField
 from taggit.models import Tag
 from taggit.models import Tag
 
 
 from dcim.models import Region
 from dcim.models import Region
@@ -193,6 +194,16 @@ class TagForm(BootstrapMixin, forms.ModelForm):
         fields = ['name', 'slug']
         fields = ['name', 'slug']
 
 
 
 
+class AddRemoveTagsForm(forms.Form):
+
+    def __init__(self, *args, **kwargs):
+        super(AddRemoveTagsForm, self).__init__(*args, **kwargs)
+
+        # Add add/remove tags fields
+        self.fields['add_tags'] = TagField(required=False)
+        self.fields['remove_tags'] = TagField(required=False)
+
+
 #
 #
 # Config contexts
 # Config contexts
 #
 #

+ 6 - 6
netbox/ipam/forms.py

@@ -7,7 +7,7 @@ from django.db.models import Count
 from taggit.forms import TagField
 from taggit.forms import TagField
 
 
 from dcim.models import Site, Rack, Device, Interface
 from dcim.models import Site, Rack, Device, Interface
-from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
+from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
 from tenancy.forms import TenancyForm
 from tenancy.forms import TenancyForm
 from tenancy.models import Tenant
 from tenancy.models import Tenant
 from utilities.forms import (
 from utilities.forms import (
@@ -68,7 +68,7 @@ class VRFCSVForm(forms.ModelForm):
         }
         }
 
 
 
 
-class VRFBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class VRFBulkEditForm(BootstrapMixin, AddRemoveTagsForm, 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(
     enforce_unique = forms.NullBooleanField(
@@ -153,7 +153,7 @@ class AggregateCSVForm(forms.ModelForm):
         fields = Aggregate.csv_headers
         fields = Aggregate.csv_headers
 
 
 
 
-class AggregateBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class AggregateBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Aggregate.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=Aggregate.objects.all(), widget=forms.MultipleHiddenInput)
     rir = forms.ModelChoiceField(queryset=RIR.objects.all(), required=False, label='RIR')
     rir = forms.ModelChoiceField(queryset=RIR.objects.all(), required=False, label='RIR')
     date_added = forms.DateField(required=False)
     date_added = forms.DateField(required=False)
@@ -346,7 +346,7 @@ class PrefixCSVForm(forms.ModelForm):
                 raise forms.ValidationError("Multiple VLANs with VID {} found".format(vlan_vid))
                 raise forms.ValidationError("Multiple VLANs with VID {} found".format(vlan_vid))
 
 
 
 
-class PrefixBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Prefix.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=Prefix.objects.all(), widget=forms.MultipleHiddenInput)
     site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False)
     site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False)
     vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, label='VRF')
     vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, label='VRF')
@@ -678,7 +678,7 @@ class IPAddressCSVForm(forms.ModelForm):
         return ipaddress
         return ipaddress
 
 
 
 
-class IPAddressBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=IPAddress.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=IPAddress.objects.all(), widget=forms.MultipleHiddenInput)
     vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, label='VRF')
     vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, label='VRF')
     tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
     tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
@@ -869,7 +869,7 @@ class VLANCSVForm(forms.ModelForm):
                     raise forms.ValidationError("Global VLAN group {} not found".format(group_name))
                     raise forms.ValidationError("Global VLAN group {} not found".format(group_name))
 
 
 
 
-class VLANBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=VLAN.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=VLAN.objects.all(), widget=forms.MultipleHiddenInput)
     site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False)
     site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False)
     group = forms.ModelChoiceField(queryset=VLANGroup.objects.all(), required=False)
     group = forms.ModelChoiceField(queryset=VLANGroup.objects.all(), required=False)

+ 2 - 1
netbox/secrets/forms.py

@@ -7,6 +7,7 @@ from django.db.models import Count
 from taggit.forms import TagField
 from taggit.forms import TagField
 
 
 from dcim.models import Device
 from dcim.models import Device
+from extras.forms import AddRemoveTagsForm
 from utilities.forms import BootstrapMixin, BulkEditForm, FilterChoiceField, FlexibleModelChoiceField, SlugField
 from utilities.forms import BootstrapMixin, BulkEditForm, FilterChoiceField, FlexibleModelChoiceField, SlugField
 from .models import Secret, SecretRole, UserKey
 from .models import Secret, SecretRole, UserKey
 
 
@@ -128,7 +129,7 @@ class SecretCSVForm(forms.ModelForm):
         return s
         return s
 
 
 
 
-class SecretBulkEditForm(BootstrapMixin, BulkEditForm):
+class SecretBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Secret.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=Secret.objects.all(), widget=forms.MultipleHiddenInput)
     role = forms.ModelChoiceField(queryset=SecretRole.objects.all(), required=False)
     role = forms.ModelChoiceField(queryset=SecretRole.objects.all(), required=False)
     name = forms.CharField(max_length=100, required=False)
     name = forms.CharField(max_length=100, required=False)

+ 2 - 2
netbox/tenancy/forms.py

@@ -4,7 +4,7 @@ from django import forms
 from django.db.models import Count
 from django.db.models import Count
 from taggit.forms import TagField
 from taggit.forms import TagField
 
 
-from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
+from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
 from utilities.forms import (
 from utilities.forms import (
     APISelect, BootstrapMixin, ChainedFieldsMixin, ChainedModelChoiceField, CommentField, FilterChoiceField, SlugField,
     APISelect, BootstrapMixin, ChainedFieldsMixin, ChainedModelChoiceField, CommentField, FilterChoiceField, SlugField,
 )
 )
@@ -69,7 +69,7 @@ class TenantCSVForm(forms.ModelForm):
         }
         }
 
 
 
 
-class TenantBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class TenantBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Tenant.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=Tenant.objects.all(), widget=forms.MultipleHiddenInput)
     group = forms.ModelChoiceField(queryset=TenantGroup.objects.all(), required=False)
     group = forms.ModelChoiceField(queryset=TenantGroup.objects.all(), required=False)
 
 

+ 6 - 0
netbox/utilities/views.py

@@ -543,6 +543,12 @@ class BulkEditView(GetReturnURLMixin, View):
                                     cfv.value = form.cleaned_data[name]
                                     cfv.value = form.cleaned_data[name]
                                     cfv.save()
                                     cfv.save()
 
 
+                            # Add/remove tags
+                            if form.cleaned_data.get('add_tags', None):
+                                obj.tags.add(*form.cleaned_data['add_tags'])
+                            if form.cleaned_data.get('remove_tags', None):
+                                obj.tags.remove(*form.cleaned_data['remove_tags'])
+
                             updated_count += 1
                             updated_count += 1
 
 
                     if updated_count:
                     if updated_count:

+ 3 - 3
netbox/virtualization/forms.py

@@ -10,7 +10,7 @@ from dcim.constants import IFACE_FF_VIRTUAL, IFACE_MODE_ACCESS, IFACE_MODE_TAGGE
 from dcim.forms import INTERFACE_MODE_HELP_TEXT
 from dcim.forms import INTERFACE_MODE_HELP_TEXT
 from dcim.formfields import MACAddressFormField
 from dcim.formfields import MACAddressFormField
 from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
 from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
-from extras.forms import CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
+from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
 from ipam.models import IPAddress
 from ipam.models import IPAddress
 from tenancy.forms import TenancyForm
 from tenancy.forms import TenancyForm
 from tenancy.models import Tenant
 from tenancy.models import Tenant
@@ -119,7 +119,7 @@ class ClusterCSVForm(forms.ModelForm):
         fields = Cluster.csv_headers
         fields = Cluster.csv_headers
 
 
 
 
-class ClusterBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Cluster.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=Cluster.objects.all(), widget=forms.MultipleHiddenInput)
     type = forms.ModelChoiceField(queryset=ClusterType.objects.all(), required=False)
     type = forms.ModelChoiceField(queryset=ClusterType.objects.all(), required=False)
     group = forms.ModelChoiceField(queryset=ClusterGroup.objects.all(), required=False)
     group = forms.ModelChoiceField(queryset=ClusterGroup.objects.all(), required=False)
@@ -349,7 +349,7 @@ class VirtualMachineCSVForm(forms.ModelForm):
         fields = VirtualMachine.csv_headers
         fields = VirtualMachine.csv_headers
 
 
 
 
-class VirtualMachineBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
+class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=VirtualMachine.objects.all(), widget=forms.MultipleHiddenInput)
     pk = forms.ModelMultipleChoiceField(queryset=VirtualMachine.objects.all(), widget=forms.MultipleHiddenInput)
     status = forms.ChoiceField(choices=add_blank_choice(VM_STATUS_CHOICES), required=False, initial='')
     status = forms.ChoiceField(choices=add_blank_choice(VM_STATUS_CHOICES), required=False, initial='')
     cluster = forms.ModelChoiceField(queryset=Cluster.objects.all(), required=False)
     cluster = forms.ModelChoiceField(queryset=Cluster.objects.all(), required=False)