philipn/django-rest-framework-filters

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.