You are on the right track. However, build_filters
is supposed to transition resource lookup to an ORM lookup.
The default implementation splits the query keyword based on __
into key_bits, value pairs and then tries to find a mapping between the resource looked up and its ORM equivalent.
Your code is not supposed to apply the filter there only build it. Here is an improved and fixed version:
def build_filters(self, filters=None):
if filters is None:
filters = {}
orm_filters = super(BusinessResource, self).build_filters(filters)
if('query' in filters):
query = filters['query']
qset = (
Q(name__icontains=query) |
Q(description__icontains=query) |
Q(email__icontains=query)
)
orm_filters.update({'custom': qset})
return orm_filters
def apply_filters(self, request, applicable_filters):
if 'custom' in applicable_filters:
custom = applicable_filters.pop('custom')
else:
custom = None
semi_filtered = super(BusinessResource, self).apply_filters(request, applicable_filters)
return semi_filtered.filter(custom) if custom else semi_filtered
Because you are using Q objects, the standard apply_filters
method is not smart enough to apply your custom filter key (since there is none), however you can quickly override it and add a special filter called “custom”. In doing so your build_filters
can find an appropriate filter, construct what it means and pass it as custom to apply_filters which will simply apply it directly rather than trying to unpack its value from a dictionary as an item.