1
If you’re doing this with the Django Rest Framework (DRF), you will want to use django_filters as referenced by DRF.
To do what you’re talking about in my project, I created a generic extension of a django_filters.Filter
:
import operator
from django.db.models import Q
import django_filters
class MultiFieldFilter(django_filters.Filter):
def __init__(self,names,*args,**kwargs):
if len(args) == 0:
kwargs['name'] = names[0]
self.token_prefix = kwargs.pop('token_prefix','')
self.token_suffix = kwargs.pop('token_suffix','')
self.token_reducer = kwargs.pop('token_reducer',operator.and_)
self.names = names
django_filters.Filter.__init__(self,*args,**kwargs)
def filter(self,qs,value):
if value not in (None,''):
tokens = value.split(',')
return qs.filter(
reduce(
self.token_reducer,
[
reduce(
operator.or_,
[Q(**{
'%s__icontains'%name:
(self.token_prefix+token+self.token_suffix)})
for name in self.names])
for token in tokens]))
return qs
This is used in a django_filter.FilterSet
like this:
class SampleSetFilter(django_filters.FilterSet):
multi_field_search = MultiFieldFilter(names=["field_foo", "bar", "baz"],lookup_type='in')
class Meta:
model = SampleSet
fields = ('multi_field_srch',)
Which is instantiated like:
class SampleSetViewSet(viewsets.ModelViewSet):
queryset = SampleSet.objects.all()
serializer_class = SampleSetSerializer
filter_class = SampleSetFilterSet # <- and vvvvvvvvvvvvvvvvvvvvvvvvvvvv
filter_backends = (filters.OrderingFilter, filters.DjangoFilterBackend,)
Finally, a GET
request like:
http://www.example.com/rest/SampleSet/?multi_field_srch=foo,de,fa,fa
will return all SampleSet
‘s that have all of foo
, de
, and fa
in at least one of the fields field_foo
, bar
, or baz
.
If you specify parameter token_reducer
to be operator.or_
, then that query would return all SampleSet
s that have any of foo
, de
, or fa
in at least one of the fields field_foo
, bar
, or baz
.
Finally, token_prefix
and token_suffix
are a way to insert wild cards (substring matching) or other prefixes or suffixes.
1
I don’t think there’s an automatic way to do this in django. But you can always OR multiple searches together using Q. The basic usage of Q is as follows:
from django.db.models import Q
Education.objects.filter(
Q(degree__icontains=query) | Q(field__icontains=query)
To use multiple queries you can easily build together these statements using a for statement (assuming queries is a list or set of query strings):
q = Q()
for query in queries
q = q | Q(degree__icontains=query) | Q(field__icontains=query)
Education.objects.filter(q)
Now you’d want to search over multiple models, so you would have to include those joins as well. It’s not exactly clear from your question how you’d want to search, but I’d guess you’d like to basically search for candidates and that all keywords need to be matched by the found items. So the query could be done like this:
q = Q()
for query in queries
q = (q & (Q(education__degree__icontains=query) |
Q(education__field__icontains=query) |
Q(resume__skill__icontains=query) |
Q(resume__role__icontains=query)
Q(skill__icontains=query) |
Q(role__icontains=query) |
Q(degree__icontains=query) |
Q(field__icontains=query)))
return Candidate.objects.filter(q)
- [Answered ]-Django Does Not Write Logs to File
- [Answered ]-Django inclusion tag takes_context TemplateDoesNotExist error
- [Answered ]-Django (1.6.3) Model.save() method not working
- [Answered ]-Prevent change of field if related objects exist?
- [Answered ]-How to chain a queryset together in Django correctly
0
I’m using Django Rest Multiple Models to search on multiple models in Django Rest Framework. Make sure to read the docs carefully, especially the section on using viewsets which explains how to set up your endpoints. It seems really well built and documented, and to support everything I expect such as limits and filters.