2

I have a Model admin where I override get_search_result this way

def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = super(OccupancyAdmin, 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

The suggestion comes from here: Is there a way to search for multiple terms in admin search? django

The problem I am facing is the following: neither the DateTimeRangeFilter from rangefilter nor my custom SimpleListFilter work as expected anymore. The filters seem like being disabled.

I looked at the SQL queries being performed and they seem alright.

I am pretty sure I am messing up with the querysets somehow but don't know how to debug this.

Maxime Georges
  • 156
  • 2
  • 7

2 Answers2

2

What worked for me was declaring an original queryset before the super(), and finally doing an interception of both querysets:

def get_search_results(self, request, queryset, search_term):
    orig_queryset = queryset
    queryset, use_distinct = super().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

Otherwise, using @simon-spa's answer any modifications performed via the modified get_search_results() would be ignored (but filters would indeed work).

Stunts
  • 430
  • 6
  • 11
1

Django first applies filters and then passes the resulting queryset to the search method. In your code, you are adding additional objects to the queryset via self.model.objects.filter() which basically renders the filter useless.

If you apply the filter only to the current queryset it works:

def get_search_results(self, request, queryset, search_term):
    queryset, use_distinct = super().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 = queryset.filter(reduce(or_, q_objects))
    return queryset, use_distinct
sosa5001
  • 53
  • 6