Skip to content

Commit

Permalink
Improve the QuerySearchFilter to provide multiple search fields #1520
Browse files Browse the repository at this point in the history
Signed-off-by: tdruez <[email protected]>
  • Loading branch information
tdruez committed Jan 8, 2025
1 parent 6d2a4c4 commit 1d5a5e4
Showing 1 changed file with 22 additions and 21 deletions.
43 changes: 22 additions & 21 deletions scanpipe/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ def filter_for_lookup(cls, field, lookup_type):
return super().filter_for_lookup(field, lookup_type)


def parse_query_string_to_lookups(query_string, default_lookup_expr, default_field):
def parse_query_string_to_lookups(query_string, default_lookup_expr, search_fields):
"""Parse a query string and convert it into queryset lookups using Q objects."""
lookups = Q()
terms = shlex.split(query_string)
Expand Down Expand Up @@ -295,11 +295,14 @@ def parse_query_string_to_lookups(query_string, default_lookup_expr, default_fie
field_name = field_name[1:]
negated = True

lookups &= Q(
**{f"{field_name}__{lookup_expr}": search_value}, _negated=negated
)

else:
search_value = term
field_name = default_field

lookups &= Q(**{f"{field_name}__{lookup_expr}": search_value}, _negated=negated)
for field_name in search_fields:
lookups |= Q(**{f"{field_name}__{lookup_expr}": search_value})

return lookups

Expand All @@ -323,18 +326,22 @@ class QuerySearchFilter(django_filters.CharFilter):

field_class = QuerySearchField

def __init__(self, search_fields=None, lookup_expr="icontains", *args, **kwargs):
super().__init__(lookup_expr=lookup_expr, *args, **kwargs)
self.search_fields = search_fields or []

def filter(self, qs, value):
if not value:
return qs

lookups = parse_query_string_to_lookups(
query_string=value,
default_lookup_expr=self.lookup_expr,
default_field=self.field_name,
search_fields=self.search_fields,
)

try:
return qs.filter(lookups)
return qs.filter(lookups).distinct()
except FieldError:
return qs.none()

Expand All @@ -347,7 +354,7 @@ class ProjectFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):
]

search = QuerySearchFilter(
label="Search", field_name="name", lookup_expr="icontains"
label="Search", search_fields=["name", "labels__name"], lookup_expr="icontains"
)
sort = django_filters.OrderingFilter(
label="Sort",
Expand Down Expand Up @@ -508,7 +515,7 @@ class ResourceFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):

search = QuerySearchFilter(
label="Search",
field_name="path",
search_fields=["path"],
lookup_expr="icontains",
)
sort = django_filters.OrderingFilter(
Expand Down Expand Up @@ -615,15 +622,7 @@ def filter(self, qs, value):
if value.startswith("pkg:"):
return qs.for_package_url(value)

if ":" in value:
return super().filter(qs, value)

search_fields = ["type", "namespace", "name", "version"]
lookups = Q()
for field_names in search_fields:
lookups |= Q(**{f"{field_names}__{self.lookup_expr}": value})

return qs.filter(lookups)
return super().filter(qs, value)


class GroupOrderingFilter(django_filters.OrderingFilter):
Expand Down Expand Up @@ -662,7 +661,9 @@ class PackageFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):
]

search = DiscoveredPackageSearchFilter(
label="Search", field_name="name", lookup_expr="icontains"
label="Search",
search_fields=["type", "namespace", "name", "version"],
lookup_expr="icontains",
)
sort = GroupOrderingFilter(
label="Sort",
Expand Down Expand Up @@ -746,7 +747,7 @@ class DependencyFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):
]

search = QuerySearchFilter(
label="Search", field_name="name", lookup_expr="icontains"
label="Search", search_fields=["name"], lookup_expr="icontains"
)
sort = GroupOrderingFilter(
label="Sort",
Expand Down Expand Up @@ -803,7 +804,7 @@ class Meta:

class ProjectMessageFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):
search = QuerySearchFilter(
label="Search", field_name="description", lookup_expr="icontains"
label="Search", search_fields=["description"], lookup_expr="icontains"
)
sort = django_filters.OrderingFilter(
label="Sort",
Expand Down Expand Up @@ -855,7 +856,7 @@ class RelationFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):

search = QuerySearchFilter(
label="Search",
field_name="to_resource__path",
search_fields=["to_resource__path"],
lookup_expr="icontains",
)
sort = django_filters.OrderingFilter(
Expand Down

0 comments on commit 1d5a5e4

Please sign in to comment.