Reputation: 1567
I am trying to create a dynamic search in this ListView I have. My idea is to specify the fields and the type of search each time I try to inherit this view.
My problem is that every time I try to make a search, it works only on the first field of the tuple. In my example: requests__email
is the first field, and when I print the object query_q
after making a query for 'app', I get the following output:
(OR: (AND: ), ('requests__email__icontains', 'app'), (AND: ('requests__email__icontains', 'app'), ('status__icontains', 'app')), (AND: ('requests__email__icontains', 'app'), ('status__icontains', 'app'), ('license_type__name__icontains', 'app')))
I don't understand why, because I am using the operator I thought it would work |=
in query_q |= Q(**query_kwargs)
. If I try to make a search based on the other attributes, status
for example, the search doesn't work.
class DefaultListView(ListView):
searchable_fields = (
('requests__email', 'icontains'),
('status', 'icontains'),
('license_type__name', 'icontains'),
)
def get_queryset(self):
form = self.form_class(self.request.GET)
if form.is_valid():
if not self.searchable_fields:
raise AttributeError('searchable_fields has not been configured.')
term = form.cleaned_data['term']
query_kwargs = dict()
query_q = Q()
# Build a list of Q objects based on the searchable attribute
for field, search_type in self.searchable_fields:
query_kwargs["{0}__{1}".format(field, search_type)] = term
query_q |= Q(**query_kwargs)
ordering = self.get_ordering()
queryset = self.model.objects.filter(query_q)
if ordering:
return queryset.order_by(**ordering)
return queryset
return super(DefaultListView, self).get_queryset()
Upvotes: 3
Views: 1324
Reputation: 3542
If you are wanting to build the query as X = Y OR W = Z it's because of
query_kwargs["{0}__{1}".format(field, search_type)] = term
You're adding more keys to query_kwargs
with each iteration of the loop rather than re-creating the variable
Would suggest something like this
for field, search_type in self.searchable_fields:
query_q |= Q(**{"{0}__{1}".format(field, search_type): term})
Upvotes: 3