Skip to content

Commit

Permalink
Make id filter work for combined endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
daanvdk committed May 22, 2024
1 parent 3388534 commit 5e0e08b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 6 deletions.
40 changes: 34 additions & 6 deletions binder/plugins/views/combined.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def combined_view(request, router, names):

# Get filtered & annotated querysets per name
querysets = {}
for name in names:
for i, name in enumerate(names):
view = views[name]

queryset = view.get_queryset(request)
Expand All @@ -92,11 +92,39 @@ def combined_view(request, router, names):
queryset = annotate(queryset, request, sub_include_annotations.get(''))

# filters
filters = {
'id' if k == f'.{name}' else k[len(name) + 2:]: v
for k, v in request.GET.lists()
if k == f'.{name}' or k.startswith(f'.{name}.')
}
filters = {}
for k, v in request.GET.lists():
if k == '.id' or k.startswith('.id:'):
values = []
for value in v:
ids = []
for id in value.split(','):
try:
id = int(id)
except ValueError:
# leave invalid values for the detailed view
pass
else:
if id % len(names) == i:
# this is a combined id that matches this view,
# so we can convert it to an id for the model
# itself
id = str(id // len(names))
else:
# this id does not match this view, so we
# convert it to an id that never matches any
# model
id = '-1'
ids.append(id)
values.append(','.join(ids))
filters[k[1:]] = values

elif k == f'.{name}' or k.startswith(f'.{name}:'):
filters['id' + k[len(name) + 1:]] = v

elif k.startswith(f'.{name}.'):
filters[k[len(name) + 2:]] = v

for field, values in filters.items():
for v in values:
q, distinct = view._parse_filter(field, v, request, sub_include_annotations)
Expand Down
15 changes: 15 additions & 0 deletions tests/test_combined.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,18 @@ def test_combined_order_by_multi_field(self):
animal2.id * 2 + 1, # Harambe
zoo1.id * 2, # Apenheul
])

def test_combined_id_filter(self):
zoo1 = Zoo.objects.create(name='Apenheul', founding_date='1980-01-01')
zoo2 = Zoo.objects.create(name='Emmen', founding_date='1990-01-01')
animal1 = Animal.objects.create(zoo=zoo1, name='Bokito', birth_date='1995-01-01')
animal2 = Animal.objects.create(zoo=zoo2, name='Harambe', birth_date='1985-01-01')

res = self.client.get(f'/combined/zoo/animal/?.id:in={zoo1.id * 2},{animal2.id * 2 + 1}')
self.assertEqual(res.status_code, 200)
data = json.loads(res.content)
ids = {obj['id'] for obj in data['data']}
self.assertEqual(ids, {
zoo1.id * 2, # Apenheul
animal2.id * 2 + 1, # Harambe
})

0 comments on commit 5e0e08b

Please sign in to comment.