In the django admin search bar if i had a model with a column = fruit_name and I wanted to search that column for all instances with either the fruit_name = banana or apple which would show all of the bananas and apples, how could I do that?
Override the ModelAdmin.get_search_results` method:
from operator import or_
from django.db.models import Q
class MyAdmin(admin.ModelAdmin):
...
def get_search_results(self, request, queryset, search_term):
queryset, use_distinct = super(MyAdmin, self).get_search_results(
request, queryset, search_term)
search_words = search_term.split()
if search_words:
q_objects = [Q(**{field + '__icontains': word})
for field in self.search_fields
for word in search_words]
queryset |= self.model.objects.filter(reduce(or_, q_objects))
return queryset, use_distinct
In my case, using @catavaran's answer would break filters as asked here. I came up with the following work-around:
from operator import or_
from django.db.models import Q
class MyAdmin(admin.ModelAdmin):
...
def get_search_results(self, request, queryset, search_term):
orig_queryset = queryset
queryset, use_distinct = super(MyAdmin, self).get_search_results(
request, queryset, search_term)
search_words = search_term.split()
if search_words:
q_objects = [Q(**{field + '__icontains': word})
for field in self.search_fields
for word in search_words]
queryset |= self.model.objects.filter(reduce(or_, q_objects))
queryset = queryset & orig_queryset
return queryset, use_distinct
This makes sure that ant previous filtering is not overridden when we use queryset |= self.model.objects.filter(reduce(or_, q_objects))
. The use of orig_queryset
, on the other hand, ensures that any chosen filters also get applied.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With