diff --git a/docs/plugins/development/filtersets.md b/docs/plugins/development/filtersets.md index d803ce2f4..b0059029a 100644 --- a/docs/plugins/development/filtersets.md +++ b/docs/plugins/development/filtersets.md @@ -61,6 +61,11 @@ class MyModelViewSet(...): The `TagFilter` class is available for all models which support tag assignment (those which inherit from `NetBoxModel` or `TagsMixin`). This filter subclasses django-filter's `ModelMultipleChoiceFilter` to work with NetBox's `TaggedItem` class. +This class filters `tags` using the `slug` field. For example: + +`GET /api/dcim/sites/?tag=alpha&tag=bravo` + + ```python from django_filters import FilterSet from extras.filters import TagFilter @@ -68,3 +73,19 @@ from extras.filters import TagFilter class MyModelFilterSet(FilterSet): tag = TagFilter() ``` + +### TagIDFilter + +The `TagIDFilter` class is available for all models which support tag assignment (those which inherit from `NetBoxModel` or `TagsMixin`). This filter subclasses django-filter's `ModelMultipleChoiceFilter` to work with NetBox's `TaggedItem` class. + +This class filters `tags` using the `id` field. For example: + +`GET /api/dcim/sites/?tag_id=100&tag_id=200` + +```python +from django_filters import FilterSet +from extras.filters import TagIDFilter + +class MyModelFilterSet(FilterSet): + tag_id = TagIDFilter() +``` diff --git a/netbox/extras/filters.py b/netbox/extras/filters.py index de739aa59..d05800c22 100644 --- a/netbox/extras/filters.py +++ b/netbox/extras/filters.py @@ -4,6 +4,7 @@ from .models import Tag __all__ = ( 'TagFilter', + 'TagIDFilter', ) @@ -20,3 +21,18 @@ class TagFilter(django_filters.ModelMultipleChoiceFilter): kwargs.setdefault('queryset', Tag.objects.all()) super().__init__(*args, **kwargs) + + +class TagIDFilter(django_filters.ModelMultipleChoiceFilter): + """ + Match on one or more assigned tags. If multiple tags are specified (e.g. ?tag=1&tag=2), the queryset is filtered + to objects matching all tags. + """ + def __init__(self, *args, **kwargs): + + kwargs.setdefault('field_name', 'tags__id') + kwargs.setdefault('to_field_name', 'id') + kwargs.setdefault('conjoined', True) + kwargs.setdefault('queryset', Tag.objects.all()) + + super().__init__(*args, **kwargs) diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py index 4f40ce500..f4ef5b453 100644 --- a/netbox/extras/filtersets.py +++ b/netbox/extras/filtersets.py @@ -11,7 +11,7 @@ from users.models import Group, User from utilities.filters import ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter from virtualization.models import Cluster, ClusterGroup, ClusterType from .choices import * -from .filters import TagFilter +from .filters import TagFilter, TagIDFilter from .models import * __all__ = ( @@ -665,6 +665,7 @@ class ConfigTemplateFilterSet(ChangeLoggedModelFilterSet): label=_('Data file (ID)'), ) tag = TagFilter() + tag_id = TagIDFilter() class Meta: model = ConfigTemplate diff --git a/netbox/netbox/filtersets.py b/netbox/netbox/filtersets.py index b8fbe7ad5..eaead5e74 100644 --- a/netbox/netbox/filtersets.py +++ b/netbox/netbox/filtersets.py @@ -10,7 +10,7 @@ from django.utils.translation import gettext as _ from core.choices import ObjectChangeActionChoices from core.models import ObjectChange from extras.choices import CustomFieldFilterLogicChoices -from extras.filters import TagFilter +from extras.filters import TagFilter, TagIDFilter from extras.models import CustomField, SavedFilter from utilities.constants import ( FILTER_CHAR_BASED_LOOKUP_MAP, FILTER_NEGATION_LOOKUP_MAP, FILTER_TREENODE_NEGATION_LOOKUP_MAP, @@ -286,6 +286,7 @@ class NetBoxModelFilterSet(ChangeLoggedModelFilterSet): label=_('Search'), ) tag = TagFilter() + tag_id = TagIDFilter() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)