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

Closes #5121: Add content_type filters for tags

This commit is contained in:
jeremystretch
2021-05-21 17:05:32 -04:00
parent b6660c72e1
commit 5b4793a2d5
3 changed files with 57 additions and 3 deletions

View File

@ -6,7 +6,7 @@ from django.db.models import Q
from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup
from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet
from tenancy.models import Tenant, TenantGroup
from utilities.filters import ContentTypeFilter
from utilities.filters import ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter
from virtualization.models import Cluster, ClusterGroup
from .choices import *
from .models import *
@ -114,6 +114,12 @@ class TagFilterSet(ChangeLoggedModelFilterSet):
method='search',
label='Search',
)
content_type = MultiValueCharFilter(
method='_content_type'
)
content_type_id = MultiValueNumberFilter(
method='_content_type_id'
)
class Meta:
model = Tag
@ -127,6 +133,32 @@ class TagFilterSet(ChangeLoggedModelFilterSet):
Q(slug__icontains=value)
)
def _content_type(self, queryset, name, values):
ct_filter = Q()
# Compile list of app_label & model pairings
for value in values:
try:
app_label, model = value.lower().split('.')
ct_filter |= Q(
app_label=app_label,
model=model
)
except ValueError:
pass
# Get ContentType instances
content_types = ContentType.objects.filter(ct_filter)
return queryset.filter(extras_taggeditem_items__content_type__in=content_types).distinct()
def _content_type_id(self, queryset, name, values):
# Get ContentType instances
content_types = ContentType.objects.filter(pk__in=values)
return queryset.filter(extras_taggeditem_items__content_type__in=content_types).distinct()
class ConfigContextFilterSet(ChangeLoggedModelFilterSet):
q = django_filters.CharFilter(

View File

@ -8,12 +8,13 @@ from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGrou
from tenancy.models import Tenant, TenantGroup
from utilities.forms import (
add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect,
CommentField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2,
BOOLEAN_WITH_BLANK_CHOICES,
CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField,
JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES,
)
from virtualization.models import Cluster, ClusterGroup
from .choices import *
from .models import ConfigContext, CustomField, ImageAttachment, JournalEntry, ObjectChange, Tag
from .utils import FeatureQuery
#
@ -180,6 +181,11 @@ class TagFilterForm(BootstrapMixin, forms.Form):
required=False,
label=_('Search')
)
content_type_id = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.filter(FeatureQuery('tags').get_query()),
required=False,
label=_('Tagged object type')
)
class TagBulkEditForm(BootstrapMixin, BulkEditForm):

View File

@ -5,6 +5,7 @@ from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from circuits.models import Provider
from dcim.models import DeviceRole, DeviceType, Manufacturer, Platform, Rack, Region, Site, SiteGroup
from extras.choices import JournalEntryKindChoices, ObjectChangeActionChoices
from extras.filtersets import *
@ -537,6 +538,13 @@ class TagTestCase(TestCase, ChangeLoggedFilterSetTests):
)
Tag.objects.bulk_create(tags)
# Apply some tags so we can filter by content type
site = Site.objects.create(name='Site 1', slug='site-1')
provider = Provider.objects.create(name='Provider 1', slug='provider-1')
site.tags.set(tags[0])
provider.tags.set(tags[1])
def test_name(self):
params = {'name': ['Tag 1', 'Tag 2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
@ -549,6 +557,14 @@ class TagTestCase(TestCase, ChangeLoggedFilterSetTests):
params = {'color': ['ff0000', '00ff00']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_content_type(self):
params = {'content_type': ['dcim.site', 'circuits.provider']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
site_ct = ContentType.objects.get_for_model(Site).pk
provider_ct = ContentType.objects.get_for_model(Provider).pk
params = {'content_type_id': [site_ct, provider_ct]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
class ObjectChangeTestCase(TestCase, BaseFilterSetTests):
queryset = ObjectChange.objects.all()