Skip to content

Commit

Permalink
Support multiword negated filters
Browse files Browse the repository at this point in the history
  • Loading branch information
stevelacey committed Jan 14, 2022
1 parent 64ad1cc commit 637bc38
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 9 deletions.
4 changes: 2 additions & 2 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ def test_profile_list_or_filter(client, db, profile_factory, tag_factory):


def test_profile_list_negated_filter(client, db, profile, user):
response = client.get(f"/profiles/?name!={user.first_name} {user.last_name}")
response = client.get(f"/profiles/?firstName!={user.first_name}")
result = response.json()
assert response.status_code == 200, result
assert len(result["profiles"]) == 0


def test_profile_list_negated__icontains__filter(client, db, profile, user):
response = client.get(f"/profiles/?name__icontains!={user.first_name}")
response = client.get(f"/profiles/?firstName__icontains!={user.first_name}")
result = response.json()
assert response.status_code == 200, result
assert len(result["profiles"]) == 0
Expand Down
7 changes: 6 additions & 1 deletion tests/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,19 @@
class ProfileList(CreateAPI, ListAPI):
model = Profile
queryset = Profile.objects.annotate(
name=Concat("user__first_name", Value(" "), "user__last_name"),
first_name=F("user__first_name"),
last_name=F("user__last_name"),
name=Concat("first_name", Value(" "), "last_name"),
date_joined=F("user__date_joined"),
)
ordering = ["pk"]
serializer = ProfileSerializer
permissions = [PublicEndpoint]
search_fields = []
filter_fields = [
"first_name",
"first_name__icontains",
"last_name",
"name",
"name__icontains",
"name__in",
Expand Down
10 changes: 7 additions & 3 deletions worf/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,19 @@ def get_parts(self, request):

return request.parse_file_upload(request.META, BytesIO(request.body))

def set_bundle(self, raw_bundle):
def set_bundle(self, raw_bundle, allow_negated_keys=False):
self.bundle = {}
self.keymap = {}

if not raw_bundle:
return

for key in raw_bundle.keys():
field = camel_to_snake(key)
field = (
camel_to_snake(key[:-1]) + "!"
if allow_negated_keys and key.endswith("!")
else camel_to_snake(key)
)
self.bundle[field] = raw_bundle[key]
self.keymap[field] = key

Expand All @@ -221,7 +225,7 @@ def set_bundle_from_query_string(self, request):
for key, value in raw_bundle.items()
}

self.set_bundle(coerced_bundle)
self.set_bundle(coerced_bundle, allow_negated_keys=True)

def set_bundle_from_request_body(self, request):
raw_bundle = {}
Expand Down
6 changes: 3 additions & 3 deletions worf/views/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,16 @@ def set_search_lookup_kwargs(self):
return

for key in self.bundle.keys():
strip_key = key.rstrip("!")
filter_key = key[:-1] if key.endswith("!") else key

if strip_key not in self.filter_fields:
if filter_key not in self.filter_fields:
continue

value = self.bundle[key]

# support passing `in` and `range` as lists
if isinstance(value, list):
if strip_key.endswith("__in") or strip_key.endswith("__range"):
if filter_key.endswith("__in") or filter_key.endswith("__range"):
value = ",".join(str(item) for item in value)

self.lookup_kwargs[key] = value
Expand Down

0 comments on commit 637bc38

Please sign in to comment.