Edited to clarify the structure required.
I am working into someone else's code, and would like to modify the search behaviour – so that the query input is used as an “or” query across two fields.
Currently I have this:
forms.py
class SearchForm(forms.Form):
area = forms.ModelChoiceField(label=_('Area'), queryset=Area.objects.all(), required=False)
group = forms.ModelChoiceField(label=_('Group'), queryset=Group.objects.all(), required=False)
q = forms.CharField(required=False, label=_('Query'),)
def filter_by(self):
# TODO search using more than one field
# TODO split query string and make seaprate search by words
filters = {}
if self.cleaned_data['group']:
filters['group'] = self.cleaned_data['group']
if self.cleaned_data['area']:
filters['area'] = self.cleaned_data['area']
filters['description__icontains'] = self.cleaned_data['q']
#filters['title__icontains'] = self.cleaned_data['q']
return filters
views.py
class FilteredListView(FormMixin, ListView):
def get_form_kwargs(self):
return {
'initial': self.get_initial(),
'prefix': self.get_prefix(),
'data': self.request.GET or None
}
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
form = self.get_form(self.get_form_class())
if form.is_valid():
self.object_list = self.object_list.filter(**form.filter_by())
context = self.get_context_data(form=form)
return self.render_to_response(context)
What I would like to be able to do is take the “q” input and do something like this:
self.object_list.filter(Q(title__icontains = request.GET['q']) | Q(description__icontains = request.GET['q']))
So that results are returned where “q” is present in the “title” or the “description”, or both. But I cannot work out a way to do that with the filter_by
returning the dictionary as it currently is.
The end query should, in SQL terms, look like this:
…'group' = 1 AND 'area' = 2 AND
('title' LIKE \'%stack%\' OR 'description' LIKE \'%stack%\')…
Rather than it being all “AND” or “OR”, i.e. to be able to mix the operators. And in this case, yes the “title” or “description” have the same query input.
Is it possible to do this? I just want to update the code as lightly as possible, without reworking the whole thing.
The reason for the light touch requirement is that it is more likely to be reviewed and accepted as a pull request if it is prima facie just a small addition to existing code.
Thanks.