Fixes #22568: Fix ValueError exception when receiving an invalid `filter_id` value (#22602)

This commit is contained in:
Jeremy Stretch 2026-07-06 10:41:31 -04:00 committed by GitHub
parent 9189067f3e
commit 9c3fb57a93
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 2 deletions

View File

@ -108,9 +108,18 @@ class BaseFilterSet(django_filters.FilterSet):
# Apply any referenced SavedFilters
if data and ('filter' in data or 'filter_id' in data):
data = data.copy() # Get a mutable copy
# Coerce filter_id values to integers, ignoring any which are not valid (see #22568)
filter_ids = []
for f_id in data.pop('filter_id', []):
try:
filter_ids.append(int(f_id))
except (ValueError, TypeError):
pass
saved_filters = SavedFilter.objects.filter(
Q(slug__in=data.pop('filter', [])) |
Q(pk__in=data.pop('filter_id', []))
Q(pk__in=filter_ids)
)
for sf in saved_filters:
for key, value in sf.parameters.items():

View File

@ -1,10 +1,12 @@
import django_filters
from django.conf import settings
from django.db import models
from django.http import QueryDict
from django.test import TestCase
from mptt.fields import TreeForeignKey
from taggit.managers import TaggableManager
from core.models import ObjectType
from dcim.choices import *
from dcim.fields import MACAddressField
from dcim.filtersets import DeviceFilterSet, InterfaceFilterSet, SiteFilterSet
@ -21,7 +23,7 @@ from dcim.models import (
Site,
)
from extras.filters import TagFilter
from extras.models import TaggedItem
from extras.models import SavedFilter, TaggedItem
from ipam.filtersets import ASNFilterSet
from ipam.models import ASN, RIR
from netbox.filtersets import BaseFilterSet
@ -670,3 +672,43 @@ class DynamicFilterLookupExpressionTestCase(TestCase):
self.assertEqual(InterfaceFilterSet(params, Interface.objects.all()).qs.count(), 5)
params = {'rf_role__empty': 'false'}
self.assertEqual(InterfaceFilterSet(params, Interface.objects.all()).qs.count(), 1)
class SavedFilterApplicationTestCase(TestCase):
"""
Validate the application of referenced SavedFilters to a FilterSet's data.
"""
@classmethod
def setUpTestData(cls):
sites = (
Site(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE),
Site(name='Site 2', slug='site-2', status=SiteStatusChoices.STATUS_PLANNED),
)
Site.objects.bulk_create(sites)
cls.saved_filter = SavedFilter.objects.create(
name='Active Sites',
slug='active-sites',
parameters={'status': [SiteStatusChoices.STATUS_ACTIVE]},
)
cls.saved_filter.object_types.set([ObjectType.objects.get_for_model(Site)])
def test_filter_id_valid(self):
# A referenced SavedFilter's parameters are applied to the queryset
data = QueryDict(f'filter_id={self.saved_filter.pk}')
self.assertEqual(SiteFilterSet(data, Site.objects.all()).qs.count(), 1)
def test_filter_id_nonexistent(self):
# A non-existent (but valid integer) filter_id is ignored
data = QueryDict('filter_id=999999')
self.assertEqual(SiteFilterSet(data, Site.objects.all()).qs.count(), 2)
def test_filter_id_non_integer(self):
# A non-integer filter_id is ignored rather than raising a ValueError (#22568)
data = QueryDict('filter_id=abc')
self.assertEqual(SiteFilterSet(data, Site.objects.all()).qs.count(), 2)
def test_filter_slug(self):
# A referenced SavedFilter may also be applied by slug
data = QueryDict('filter=active-sites')
self.assertEqual(SiteFilterSet(data, Site.objects.all()).qs.count(), 1)