Complex filter returning all objects
ross-weir opened this issue · 6 comments
Hi. This is probably a mistake on my behalf but I'm having trouble getting complex filtering to return filtered items. I've searched the docs but haven't had any luck.
I am using the following filter:
(count__lt=11) & (name__icontains=hat)
%28count__lt%3D11%29%20%26%20%28name__icontains%3Dhat%29
It seems to be encoded correctly because when I make a get request it returns all of the instances and when I put a error in the encoding I receive a error about the encoding.
View:
class ItemSetView(views.ModelViewSet):
permission_classes = [permissions.IsAuthenticated]
queryset = models.Item.objects.all()
serializer_class = serializers.ItemSerializer
filter_set = filters.ItemFilter
Filter:
class ItemFilter(filters.FilterSet):
class Meta:
model = Item
fields = {"name": ["icontains"], "count": ["lt", "gt", "lte", "gte", "exact"]}
Perhaps I need to add something to my url conf?
router.register(r"items", ItemViewSet, base_name="items")
...
path("items/", include(router.urls), name="m-items"),
Any help or advice would be great. Thanks
Hi @ross-weir. Off the cuff, everything seems correct.
Can you paste the validation error that you're receiving?
Hey @rpkilby , thanks for the reply.
I purposely made a error in the following:
/items?filters=%28count__lt%253D11%29%20%7C%20%20name__exact%253DElite%29
And got this error:
{
"filters": [
"Ending querystring must not have trailing characters. Matched: ' | name__exact=Elite)'."
]
}
Although, if there are no intentional encoding errors I just always GET
back the complete list of items, unfiltered with no errors. Also I'm using the browsable API for testing, not sure if this matters
Okay, so if you're getting that error, then the complex filter backend is at least being executed, so that's a start.
In terms of solving this, my goto suggestion is to simplify the problem by removing complicating factors. Complex filters aren't working, what about regular filters? What happens if you make a JSON request instead of using the browsable API?
If that doesn't get you anywhere, then you're going to have to use breakpoints or log statements.
e.g., you may want to override the filterset __init__
and print the data. This tells you two things:
a) the filterset was actually instantiated
b) what data was provided to the filterset. Maybe data
is an empty dict.
You might also try overriding filter_queryset
, and printing the SQL query. This will give you an idea of
whether or not the filters are being applied correctly.
def filter_queryset(self, queryset):
qs = super().filter_queryset(queryset)
print(str(qs.query))
return qs
Thank you for the direction and for your time. I'll do some debugging after work and see if I can figure it out
It took me farrrrrrrr too long to actually find this issue, none of the breakpoints in filter_queryset
or __init__
would get hit but I'd get the encoding error. The cause was having:
filter_set = filters.ItemFilter
not
filter_class = filters.ItemFilter
Lol. Thanks again for your help
Nice. Glad you were able to fix it. Also, note that in django-filter 2.0, the attribute name is now filterset_class
, not filter_class
.