Skip to content

graphene-django DjangoFilterConnectionField not filtering for type ID #1078

@amarkezic

Description

@amarkezic

graphene-django uses this library to filter django model fields. Everything works fine until you try to filter a field that has graphql type ID. When exeucting query of type:

query {
  userManagerQueries {
    tenantUsers(userId: "VXNlck5vZGU6MQ==") {
	edges {
          node {
            tenantId {
              id
            }
          }
        }
      }
    }
  }

You get the all the results instead of the one you are filtering (so it like you didn't apply the filter)

After doing some digging i found out the the source of the problem is in the file
django-filters/filterset.py in the method:

    @property
    def qs(self):
        if not hasattr(self, '_qs'):
            qs = self.queryset.all()
            if self.is_bound:
                # ensure form validation before filtering
                self.errors
                qs = self.filter_queryset(qs)
            self._qs = qs
        return self._qs

Because no error is raised uppon form validation and the next method in the callstack filter_queryset (still in django-filters/filterset.py ) uses cleaned_data the error gets ignored and the filter dosen't appear in the cleaned_data dict and is not applied to the query set.

    def filter_queryset(self, queryset):
        """
        Filter the queryset with the underlying form's `cleaned_data`. You must
        call `is_valid()` or `errors` before calling this method.

        This method should be overridden if additional filtering needs to be
        applied to the queryset before it is cached.
        """

        for name, value in self.form.cleaned_data.items():
            queryset = self.filters[name].filter(queryset, value)
            assert isinstance(queryset, models.QuerySet), \
                "Expected '%s.%s' to return a QuerySet, but got a %s instead." \
                % (type(self).__name__, name, type(queryset).__name__)
        return queryset

I did a quick fix by raisging an error uppon unsuccessful form validation:

    def qs(self):
        if not hasattr(self, '_qs'):
            qs = self.queryset.all()
            if self.is_bound:
                # ensure form validation before filtering
                if len(self.errors) > 0:
                    raise Exception(self.errors)
                qs = self.filter_queryset(qs)
            self._qs = qs
        return self._qs

The question i now have is. Can this be fixed or is it intended to be this way and i have to do the form validation in some other part in my code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions