1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Tag filter field for filter forms

This commit is contained in:
Saria Hajjar
2020-01-13 20:16:13 +00:00
parent a8d9fe799b
commit 2f28dec891
7 changed files with 101 additions and 7 deletions

View File

@ -6,8 +6,8 @@ from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEdit
from tenancy.forms import TenancyFilterForm, TenancyForm from tenancy.forms import TenancyFilterForm, TenancyForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField, APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField, DatePicker,
DatePicker, FilterChoiceField, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple FilterChoiceField, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField
) )
from .constants import * from .constants import *
from .models import Circuit, CircuitTermination, CircuitType, Provider from .models import Circuit, CircuitTermination, CircuitType, Provider
@ -129,6 +129,10 @@ class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm):
label='ASN' label='ASN'
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Circuit types # Circuit types
@ -333,6 +337,10 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
label='Commit rate (Kbps)' label='Commit rate (Kbps)'
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Circuit terminations # Circuit terminations

View File

@ -23,7 +23,8 @@ from utilities.forms import (
APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm,
BulkEditNullBooleanSelect, ChainedFieldsMixin, ChainedModelChoiceField, ColorSelect, CommentField, ComponentForm, BulkEditNullBooleanSelect, ChainedFieldsMixin, ChainedModelChoiceField, ColorSelect, CommentField, ComponentForm,
ConfirmationForm, CSVChoiceField, ExpandableNameField, FilterChoiceField, FlexibleModelChoiceField, JSONField, ConfirmationForm, CSVChoiceField, ExpandableNameField, FilterChoiceField, FlexibleModelChoiceField, JSONField,
SelectWithPK, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, BOOLEAN_WITH_BLANK_CHOICES SelectWithPK, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField,
BOOLEAN_WITH_BLANK_CHOICES
) )
from virtualization.models import Cluster, ClusterGroup from virtualization.models import Cluster, ClusterGroup
from .constants import * from .constants import *
@ -335,6 +336,10 @@ class SiteFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Rack groups # Rack groups
@ -713,6 +718,10 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Rack elevations # Rack elevations
@ -1005,6 +1014,10 @@ class DeviceTypeFilterForm(BootstrapMixin, CustomFieldFilterForm):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Device component templates # Device component templates
@ -1947,6 +1960,10 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Bulk device component creation # Bulk device component creation
@ -3405,6 +3422,10 @@ class InventoryItemFilterForm(BootstrapMixin, forms.Form):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Virtual chassis # Virtual chassis
@ -3591,6 +3612,10 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Power panels # Power panels
@ -3967,3 +3992,7 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm):
max_utilization = forms.IntegerField( max_utilization = forms.IntegerField(
required=False required=False
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)

View File

@ -10,7 +10,7 @@ from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField, add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField,
CSVChoiceField, DatePicker, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, ReturnURLForm, CSVChoiceField, DatePicker, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, ReturnURLForm,
SlugField, StaticSelect2, StaticSelect2Multiple, BOOLEAN_WITH_BLANK_CHOICES SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES
) )
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from .constants import * from .constants import *
@ -103,6 +103,10 @@ class VRFFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
label='Search' label='Search'
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# RIRs # RIRs
@ -232,6 +236,10 @@ class AggregateFilterForm(BootstrapMixin, CustomFieldFilterForm):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Roles # Roles
@ -578,6 +586,10 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
label='Expand prefix hierarchy' label='Expand prefix hierarchy'
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# IP addresses # IP addresses
@ -1006,6 +1018,10 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# VLAN groups # VLAN groups
@ -1293,6 +1309,10 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Services # Services
@ -1353,6 +1373,10 @@ class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm): class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(

View File

@ -7,7 +7,7 @@ from dcim.models import Device
from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldForm from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldForm
from utilities.forms import ( from utilities.forms import (
APISelect, APISelectMultiple, BootstrapMixin, FilterChoiceField, FlexibleModelChoiceField, SlugField, APISelect, APISelectMultiple, BootstrapMixin, FilterChoiceField, FlexibleModelChoiceField, SlugField,
StaticSelect2Multiple StaticSelect2Multiple, TagFilterField
) )
from .models import Secret, SecretRole, UserKey from .models import Secret, SecretRole, UserKey
@ -185,6 +185,10 @@ class SecretFilterForm(BootstrapMixin, CustomFieldFilterForm):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# UserKeys # UserKeys

View File

@ -4,7 +4,7 @@ from taggit.forms import TagField
from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from utilities.forms import ( from utilities.forms import (
APISelect, APISelectMultiple, BootstrapMixin, ChainedFieldsMixin, ChainedModelChoiceField, CommentField, APISelect, APISelectMultiple, BootstrapMixin, ChainedFieldsMixin, ChainedModelChoiceField, CommentField,
FilterChoiceField, SlugField, FilterChoiceField, SlugField, TagFilterField
) )
from .models import Tenant, TenantGroup from .models import Tenant, TenantGroup
@ -114,6 +114,10 @@ class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# Form extensions # Form extensions

View File

@ -6,6 +6,7 @@ from io import StringIO
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from django.contrib.postgres.forms.jsonb import JSONField as _JSONField, InvalidJSONInput from django.contrib.postgres.forms.jsonb import JSONField as _JSONField, InvalidJSONInput
from django.db.models import Count
from mptt.forms import TreeNodeMultipleChoiceField from mptt.forms import TreeNodeMultipleChoiceField
from .constants import * from .constants import *
@ -596,6 +597,22 @@ class SlugField(forms.SlugField):
self.widget.attrs['slug-source'] = slug_source self.widget.attrs['slug-source'] = slug_source
class TagFilterField(forms.MultipleChoiceField):
"""
A filter field for the tags of a model. Only the tags used by a model are displayed.
:param model: The model of the filter
"""
widget = StaticSelect2Multiple
def __init__(self, model, *args, **kwargs):
if hasattr(model, 'tags'):
tags = model.tags.annotate(count=Count('extras_taggeditem_items')).order_by('name')
choices = [(str(tag.slug), '{} ({})'.format(tag.name, tag.count)) for tag in tags]
super().__init__(label='Tags', choices=choices, required=False, *args, **kwargs)
class FilterChoiceIterator(forms.models.ModelChoiceIterator): class FilterChoiceIterator(forms.models.ModelChoiceIterator):
def __iter__(self): def __iter__(self):

View File

@ -13,7 +13,7 @@ from utilities.forms import (
add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
ChainedFieldsMixin, ChainedModelChoiceField, ChainedModelMultipleChoiceField, CommentField, ComponentForm, ChainedFieldsMixin, ChainedModelChoiceField, ChainedModelMultipleChoiceField, CommentField, ComponentForm,
ConfirmationForm, CSVChoiceField, ExpandableNameField, FilterChoiceField, JSONField, SlugField, ConfirmationForm, CSVChoiceField, ExpandableNameField, FilterChoiceField, JSONField, SlugField,
SmallTextarea, StaticSelect2, StaticSelect2Multiple SmallTextarea, StaticSelect2, StaticSelect2Multiple, TagFilterField
) )
from .constants import * from .constants import *
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
@ -217,6 +217,10 @@ class ClusterFilterForm(BootstrapMixin, CustomFieldFilterForm):
) )
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form): class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
region = forms.ModelChoiceField( region = forms.ModelChoiceField(
@ -623,6 +627,10 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
label='MAC address' label='MAC address'
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
# #
# VM interfaces # VM interfaces