philipn / django-rest-framework-filters

Better filtering for Django REST Framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unexisting field in a RelatedFilter does not raise Field Error

hectorcanto opened this issue · comments

Hi,

I'm using v1.0.0.dev0 and I've set up a Custom ComplexFilterBackend with RelatedField FilterSets and when I query over an unexisting field in a relation (or an unexisting field) I don't get the expected Field Error.

Using the debugger I've applied the search manually and got what I expected:

queryset.filter(countries__badfield="Bulgaria")
*** django.core.exceptions.FieldError: Related Field got invalid lookup: badfield

My ViewSet and FilterSets are:

class CountryFilter(rest_framework_filters.filters.FilterSet):
    class Meta:
        model = Country
        fields = {'name': ['exact', 'icontains', 'startswith']}


class CustomUserFilter(rest_framework_filters.filters.FilterSet):
    countries = filters.RelatedFilter(CountryFilter, field_name='countries',
                                    queryset=Country.objects.all())

    class Meta:
        model = CustomUser
        fields = {'name': ['exact', 'in', 'startswith'],  'id': ['exact']}


class CustomUserViewSet(viewsets.GenericViewSet, mixins. RetrieveModelMixin):
    serializer_class = UserSerializer
    filter_backends = (OrderingFilter, FuzzyFilter, ComplexFilterBackend, )
    filterset_class = CustomBackendFilter

The query_strings I tried are:

['badfield=Bulgaria']
['countries_nam=Bulgaria']  # without the 'e' in name
['countries_badfield=Bulgaria']

Which I believe are encoded properly (I have tests working with valid fields already)
The QueryDict looks like
<QueryDict: {'complex': ['%28badfield%253DBulgaria%29'], 'page[limit]': ['100']}>

None of the tests raised a Field Error nor any other exception, it returns all the objects as if the filter wasn't there.

Thanks for your assistance.

Hi @hectorcanto. Generally, this is a limitation of query strings. Ignoring complex filtering for a second, think about pagination. Even though the FilterSet doesn't handle pagination, some other bit of view code does, and we wouldn't want to raise a validation error if that parameter were present. As such, it's not really possible to differentiate errors from "handled elsewhere", and there's no mechanism in query strings to indicate which parameter is associated with some feature.

With complex filtering, we could theoretically provide some bit of validation, however I don't think we'd want to do this. Under the hood, FilterSets use regular Django forms to validate its parameters, and it's possible that its form uses some additional parameters not directly related to the filters.

Long story short, this is something we wouldn't want to implement generally, although you could add this as a mixin to your own filtersets.