diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index b278f9a7c..0fefa7ae6 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -138,8 +138,11 @@ class ImageAttachmentViewSet(ModelViewSet): # class ConfigContextViewSet(ModelViewSet): - queryset = ConfigContext.objects.prefetch_related('regions', 'sites', 'roles', 'platforms', 'tenants') + queryset = ConfigContext.objects.prefetch_related( + 'regions', 'sites', 'roles', 'platforms', 'tenant_groups', 'tenants', + ) serializer_class = serializers.ConfigContextSerializer + filter_class = filters.ConfigContextFilter # diff --git a/netbox/extras/filters.py b/netbox/extras/filters.py index 71c9314cd..3abd5b4cf 100644 --- a/netbox/extras/filters.py +++ b/netbox/extras/filters.py @@ -6,9 +6,10 @@ from django.contrib.contenttypes.models import ContentType from django.db.models import Q from taggit.models import Tag -from dcim.models import Site +from dcim.models import DeviceRole, Platform, Region, Site +from tenancy.models import Tenant, TenantGroup from .constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_TYPE_BOOLEAN, CF_TYPE_SELECT -from .models import CustomField, Graph, ExportTemplate, ObjectChange, TopologyMap, UserAction +from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, TopologyMap, UserAction class CustomFieldFilter(django_filters.Filter): @@ -124,6 +125,92 @@ class TopologyMapFilter(django_filters.FilterSet): fields = ['name', 'slug'] +class ConfigContextFilter(django_filters.FilterSet): + q = django_filters.CharFilter( + method='search', + label='Search', + ) + region_id = django_filters.ModelMultipleChoiceFilter( + name='regions', + queryset=Region.objects.all(), + label='Region', + ) + region = django_filters.ModelMultipleChoiceFilter( + name='regions__slug', + queryset=Region.objects.all(), + to_field_name='slug', + label='Region (slug)', + ) + site_id = django_filters.ModelMultipleChoiceFilter( + name='sites', + queryset=Site.objects.all(), + label='Site', + ) + site = django_filters.ModelMultipleChoiceFilter( + name='sites__slug', + queryset=Site.objects.all(), + to_field_name='slug', + label='Site (slug)', + ) + role_id = django_filters.ModelMultipleChoiceFilter( + name='roles', + queryset=DeviceRole.objects.all(), + label='Role', + ) + role = django_filters.ModelMultipleChoiceFilter( + name='roles__slug', + queryset=DeviceRole.objects.all(), + to_field_name='slug', + label='Role (slug)', + ) + platform_id = django_filters.ModelMultipleChoiceFilter( + name='platforms', + queryset=Platform.objects.all(), + label='Platform', + ) + platform = django_filters.ModelMultipleChoiceFilter( + name='platforms__slug', + queryset=Platform.objects.all(), + to_field_name='slug', + label='Platform (slug)', + ) + tenant_group_id = django_filters.ModelMultipleChoiceFilter( + name='tenant_groups', + queryset=TenantGroup.objects.all(), + label='Tenant group', + ) + tenant_group = django_filters.ModelMultipleChoiceFilter( + name='tenant_groups__slug', + queryset=TenantGroup.objects.all(), + to_field_name='slug', + label='Tenant group (slug)', + ) + tenant_id = django_filters.ModelMultipleChoiceFilter( + name='tenants', + queryset=Tenant.objects.all(), + label='Tenant', + ) + tenant = django_filters.ModelMultipleChoiceFilter( + name='tenants__slug', + queryset=Tenant.objects.all(), + to_field_name='slug', + label='Tenant (slug)', + ) + + class Meta: + model = ConfigContext + fields = ['name', 'is_active'] + + def search(self, queryset, name, value): + if not value.strip(): + return queryset + return queryset.filter( + Q(name__icontains=value) | + Q(description__icontains=value) | + Q(data__icontains=value) + ) + + class ObjectChangeFilter(django_filters.FilterSet): q = django_filters.CharFilter( method='search', diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index 0b8d27233..7dfceb390 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -10,8 +10,12 @@ from mptt.forms import TreeNodeMultipleChoiceField from taggit.forms import TagField from taggit.models import Tag -from dcim.models import Region -from utilities.forms import add_blank_choice, BootstrapMixin, BulkEditForm, LaxURLField, JSONField, SlugField +from dcim.models import DeviceRole, Platform, Region, Site +from tenancy.models import Tenant, TenantGroup +from utilities.forms import ( + add_blank_choice, BootstrapMixin, BulkEditForm, FilterChoiceField, FilterTreeNodeMultipleChoiceField, LaxURLField, + JSONField, SlugField, +) from .constants import ( CF_FILTER_DISABLED, CF_TYPE_BOOLEAN, CF_TYPE_DATE, CF_TYPE_INTEGER, CF_TYPE_SELECT, CF_TYPE_URL, OBJECTCHANGE_ACTION_CHOICES, @@ -223,6 +227,37 @@ class ConfigContextForm(BootstrapMixin, forms.ModelForm): ] +class ConfigContextFilterForm(BootstrapMixin, forms.Form): + q = forms.CharField( + required=False, + label='Search' + ) + region = FilterTreeNodeMultipleChoiceField( + queryset=Region.objects.all(), + to_field_name='slug' + ) + site = FilterChoiceField( + queryset=Site.objects.all(), + to_field_name='slug' + ) + role = FilterChoiceField( + queryset=DeviceRole.objects.all(), + to_field_name='slug' + ) + platform = FilterChoiceField( + queryset=Platform.objects.all(), + to_field_name='slug' + ) + tenant_group = FilterChoiceField( + queryset=TenantGroup.objects.all(), + to_field_name='slug' + ) + tenant = FilterChoiceField( + queryset=Tenant.objects.all(), + to_field_name='slug' + ) + + # # Image attachments # diff --git a/netbox/extras/tables.py b/netbox/extras/tables.py index dd73bfe3e..22bf26cce 100644 --- a/netbox/extras/tables.py +++ b/netbox/extras/tables.py @@ -72,15 +72,10 @@ class ConfigContextTable(BaseTable): is_active = BooleanColumn( verbose_name='Active' ) - actions = tables.TemplateColumn( - template_code=CONFIGCONTEXT_ACTIONS, - attrs={'td': {'class': 'text-right'}}, - verbose_name='' - ) class Meta(BaseTable.Meta): model = ConfigContext - fields = ('pk', 'name', 'weight', 'is_active', 'description', 'actions') + fields = ('pk', 'name', 'weight', 'is_active', 'description') class ObjectChangeTable(BaseTable): diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 7c0ab67d3..90d0d698d 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -14,7 +14,7 @@ from taggit.models import Tag from utilities.forms import ConfirmationForm from utilities.views import BulkDeleteView, ObjectDeleteView, ObjectEditView, ObjectListView from . import filters -from .forms import ConfigContextForm, ImageAttachmentForm, ObjectChangeFilterForm, TagForm +from .forms import ConfigContextForm, ConfigContextFilterForm, ImageAttachmentForm, ObjectChangeFilterForm, TagForm from .models import ConfigContext, ImageAttachment, ObjectChange, ReportResult from .reports import get_report, get_reports from .tables import ConfigContextTable, ObjectChangeTable, TagTable @@ -56,6 +56,8 @@ class TagBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class ConfigContextListView(ObjectListView): queryset = ConfigContext.objects.all() + filter = filters.ConfigContextFilter + filter_form = ConfigContextFilterForm table = ConfigContextTable template_name = 'extras/configcontext_list.html' diff --git a/netbox/templates/extras/configcontext.html b/netbox/templates/extras/configcontext.html index c87ff9039..c987daf33 100644 --- a/netbox/templates/extras/configcontext.html +++ b/netbox/templates/extras/configcontext.html @@ -140,6 +140,20 @@ {% endif %} +