Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new SearchFilter for use with filtersets #1752

Merged
merged 12 commits into from
May 16, 2022
Merged

Conversation

jathanism
Copy link
Contributor

@jathanism jathanism commented May 5, 2022

Closes: #DNE

What's Changed

This implements a new SearchFilter in nautobot.utilities.filters that is intended to replace the need to always define a q filter and a search method together. The goal here is to reduce boilerplate AND to support reversible queries even on the search field by making the filter predicates used to construct the search query stored on the filter itself.

  • This replaces the need to define a search() method on every filterset for which one desires to implement search
  • This replaces all instances of q = CharFilter(method="search") and search() with SearchFilter across all filtersets in the core.

TODO

  • Explanation of Change(s)
  • Attached Screenshots, Payload Example
  • Unit, Integration Tests
  • Documentation Updates (when adding/changing features)
  • Example Plugin Updates (when adding/changing features)
  • Outline Remaining Work, Constraints from Design

- This replaces the need to define a `search()` method on every filterset for which one desires to implement search
- This replaces all instances of `q = CharFilter(method="search")` and `search()` with `SearchFilter` across all filtersets in the core.
@jathanism jathanism mentioned this pull request May 5, 2022
3 tasks
nautobot/ipam/filters.py Show resolved Hide resolved
nautobot/ipam/filters.py Outdated Show resolved Hide resolved
nautobot/utilities/filters.py Outdated Show resolved Hide resolved
nautobot/utilities/filters.py Outdated Show resolved Hide resolved
nautobot/utilities/filters.py Outdated Show resolved Hide resolved
nautobot/dcim/filters.py Show resolved Hide resolved
nautobot/utilities/filters.py Outdated Show resolved Hide resolved
nautobot/utilities/filters.py Outdated Show resolved Hide resolved
nautobot/utilities/filters.py Outdated Show resolved Hide resolved
nautobot/utilities/filters.py Show resolved Hide resolved
nautobot/utilities/filters.py Show resolved Hide resolved
nautobot/utilities/filters.py Outdated Show resolved Hide resolved
nautobot/utilities/filters.py Outdated Show resolved Hide resolved
nautobot/utilities/tests/test_filters.py Outdated Show resolved Hide resolved
q = SearchFilter(filter_predicates={"asn": {"lookup_expr": "exact", "preprocessor": dict}})

params = {"q": "1234"}
self.assertEqual(self.get_filterset_count(params, MySiteFilterSet2), Site.objects.count())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like that filters "fail open" - here we have a SearchFilter that won't match the provided query string, and the return is all Sites rather than an empty list? Does this fall under #1736 or is there something specific in the way SearchFilter is implemented that could be changed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't actually fail open. It's a side effect when there's only a single predicate defined and it fails to render causing the Q filter to "pass through". This has been corrected in the latest update to add id__iexact by default because now there will always at least be the id field.

We should actually discuss this in detail. I found that when a Q object has no predicates it actually evaluates to False vs. any other case with at least one predicate, evals to True. This could be a way for us to have some sanity check like:

if not query:
   qs = qs.none()

nautobot/dcim/filters.py Outdated Show resolved Hide resolved
nautobot/dcim/filters.py Show resolved Hide resolved
- Always pass through `strip=False` by default so the form field used for validation doesn't strip whitespace
- Automatically skip stripping `icontains` searches (paired with `strip=False` means searching with trailing spaces can be supported
- For `icontains` searches unless a preprocessor is explicitly specified, a `noop` will be used
- Fixed a small bug in `BaseFilterSet.FILTER_DEFAULTS` mapping for `JSONField` where `lookup_expr` was being passed in as a list and should be a string.
* Ability to search UUID
* Add test coverage for `q` field

Co-authored-by: zack <zack.tobar@networktocode.com>
@jathanism jathanism merged commit 5a9d9d0 into develop May 16, 2022
@jathanism jathanism deleted the jathanism-new-filters branch May 16, 2022 16:13
jathanism added a commit that referenced this pull request May 16, 2022
@bryanculver bryanculver added this to the v1.3.4 milestone May 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

4 participants