Let's say I have a queryset of Products that has tons of prefetch objects in it. Among the prefetch objects are "categories", and categories can have "filters". Not every Product has categories and filters defined.
Example categories could be "price" and "color", and filters could be "lt $5" and "blue".
I can get only the Products that have "price" and "color" defined easily enough, using exclude.
But how do I get this, for example:
All the Products that have "price"=* defined, and all the Products that have "color"="blue" defined.
Any ideas?
EDIT: I'm gonna go ahead and show the solution I came up with. Bear in mind that the example above is very much simplified. There are dozens of categories, each with dozens of filters.
Imagine that the the user chose category 'shoes' but not filters 'shoes': 'women' or 'shoes': 'football'.
And she chose category 'price' AND filter 'price': 'lt $5'
from django.db.models import Q
import operator
argument_list = []
# categories_selected = all the categories that have been checked on the page
for c in categories_selected:
# categories_filtered = all the (selected) categories that have filters applied
if c not in categories_filtered:
# Here we get all where <category>_id is defined
argument_list.append(Q(**{c+'__id__isnull': False}))
else:
for f in get_category_filters_from_url(filters_selected, c):
# get_category_filters_from_url() returns all the filters (by id) belonging
# to a given category, e.g., 'price': 'lt $5'
argument_list.append(Q(**{c+'__id': f}))
resources = resources.filter(reduce(operator.or_, argument_list)).distinct()
I hope that's clear enough, and that it helps someone else muddle through something like this.
Without knowing how your models look like, I'd use the following query:
Query with
AND
:Query with
OR
: