Search code examples
pythondjangosearch-engineadminattributeerror

Using Django Admin search engine in my own views


I am trying to use the same search engine as Django uses in the admin page to show results in my custom views.

I found this website that recommends to use the following code:

from django.db.models import Q
from django.db.models.query import QuerySet
import operator

def django_admin_keyword_search(model, keywords, base_qs=None):
    """Search according to fields defined in Admin's search_fields"""
    if not keywords: 
        return []
    fields = model._meta.admin.search_fields

    qs = QuerySet(model)

    for keyword in keywords:
        or_queries = [Q(**{'%s__icontains' % field: keyword}) for field in fields]
        if base_qs is None:
            other_qs = QuerySet(model)
        else:
            other_qs = base_qs
        if qs._select_related:
            other_qs = other_qs.select_related()
        other_qs = other_qs.filter(reduce(operator.or_, or_queries))
        qs = qs & other_qs

    return qs

def do_keyword_search(model, query, base_qs=None):
    return django_admin_keyword_search(model, query.split(' '),
                                       base_qs=base_qs)

but i am not being able to run that without getting an Attribute Error ('Options' object has no attribute 'admin') at this piece of code: fields = model._meta.admin.search_fields

EDIT: What am I doing wrong on using the admin default search engine?

Is that any other way to use the default admin search engine?


Solution

  • I managed to build my own generical search that works like the admin search. The class is as follows:

    from django.db.models import Q
    from django.db.models.query import QuerySet
    import operator
    
    def django_admin_keyword_search(model, keywords, search_fields):
        """Search according to fields defined in Admin's search_fields"""
        all_queries = None
    
        for keyword in keywords.split(' '):  #breaks query_string into 'Foo' and 'Bar'
            keyword_query = None
    
            for field in search_fields:
                each_query = Q(**{field+'__icontains':keyword})
    
                if not keyword_query:
                    keyword_query = each_query
                else:
                    keyword_query = keyword_query | each_query
    
            if not all_queries:
                all_queries = keyword_query
            else:
                all_queries = all_queries & keyword_query
    
        result_set = model.objects.filter(all_queries).distinct()
    
        return result_set
    

    Enjoy !!