Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite filtering based on Q objects #1203

Closed
wants to merge 3 commits into from

Conversation

hodossy
Copy link

@hodossy hodossy commented Apr 21, 2020

This PR rewrites the filters to use Q objects instead of subsequent filter() calls. The goal is to provide a way to support arbitraty logic for combining filters in filtersets. The idea is that the filter_queryset() function would receive a list of Q objects, and by default it calls filter with each. If overridden, any custom logic could be supported.

Related to #1167. Groups could be implemented based on this new interface as well, but some discussion is needed there.

Problems to work on:

  • Distinct calls are sometimes made before, sometimes after the filtering. What is the reason behind it?

@carltongibson What do you think of this PR? Does it worth finishing? Could you help me sort out the distinct calls?

Still left:

  • Filterset filtering rewrite
  • Doc update

@rpkilby
Copy link
Collaborator

rpkilby commented Apr 21, 2020

Hi @hodossy. This approach has been discussed before, but it's basically a nonstarter. While Q objects do have benefits (e.g., can OR them together), they also prevent you from using a whole set of queryset features, like annotations and ordering. As an example, it would not be possible to implement OrderingFilter, since that filter specifically needs to call .order_by(). This is the same issue as you're running into with .distinct(), except it's complicated by the fact that you .order_by() also requires arguments.

Unfortunately, I don't know of any good ways to work around this, except something like groups.

@hodossy
Copy link
Author

hodossy commented Apr 22, 2020

Yes, I have noticed OrderingFilter, and I have a solution for that, of course not so elegant, and I was also able to handle distinct() calls as well. (I am just not sure why some filters apply distinct before they filter, and some after.) I also run into a problem with FilterMethod, as I am afraid I cannot keep backward compatibility with it (or just in a really ugly way).

Copy link
Owner

@carltongibson carltongibson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @hodossy. Thanks for the suggestion.

I have to say, though, that I'm not at all in the market for a rewrite along these lines.

The goal is to provide a way to support arbitraty logic for combining filters in filtersets. The idea is that the filter_queryset() function would receive a list of Q objects, and by default it calls filter with each. If overridden, any custom logic could be supported.

My take on this is just override qs or filter_queryset() — if Django Filter didn't exist you'd just write a method in your view to encapsulate the filtering logic. This wouldn't be complicated. Given that Django Filter does exist, and you want to leverage the query parameter validation, you just move that logic down to your FilterSet. It's still not complicated. Much less so than adding machinery to handle arbitrary Q object composition. It's just not worth the price of entry.

I hope that makes sense.

Sorry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants