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

View File

@ -23,7 +23,8 @@ from utilities.forms import (
APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm,
BulkEditNullBooleanSelect, ChainedFieldsMixin, ChainedModelChoiceField, ColorSelect, CommentField, ComponentForm,
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 .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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -3967,3 +3992,7 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm):
max_utilization = forms.IntegerField(
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 (
add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField,
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 .constants import *
@ -103,6 +103,10 @@ class VRFFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
label='Search'
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
#
# 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
@ -578,6 +586,10 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
label='Expand prefix hierarchy'
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
#
# 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
@ -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
@ -1353,6 +1373,10 @@ class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False,
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tag'] = TagFilterField(self.model)
class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
pk = forms.ModelMultipleChoiceField(

View File

@ -7,7 +7,7 @@ from dcim.models import Device
from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldForm
from utilities.forms import (
APISelect, APISelectMultiple, BootstrapMixin, FilterChoiceField, FlexibleModelChoiceField, SlugField,
StaticSelect2Multiple
StaticSelect2Multiple, TagFilterField
)
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

View File

@ -4,7 +4,7 @@ from taggit.forms import TagField
from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from utilities.forms import (
APISelect, APISelectMultiple, BootstrapMixin, ChainedFieldsMixin, ChainedModelChoiceField, CommentField,
FilterChoiceField, SlugField,
FilterChoiceField, SlugField, TagFilterField
)
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

View File

@ -6,6 +6,7 @@ from io import StringIO
from django import forms
from django.conf import settings
from django.contrib.postgres.forms.jsonb import JSONField as _JSONField, InvalidJSONInput
from django.db.models import Count
from mptt.forms import TreeNodeMultipleChoiceField
from .constants import *
@ -596,6 +597,22 @@ class SlugField(forms.SlugField):
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):
def __iter__(self):

View File

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