How to make Q lookups in django look for multiple values
<p>Currently I have a very simple search option which goes through my pages and looks up through several fields for requested query. If I input a single word in it it works just fine, however if I input multiple words in search query, I get nothing, even if a single page contains all attributes. For example if I search for <code>test admin</code>, I will not get empty query, even though there's a page with title test, with content test and author admin. Is there a way to expand the search to look up each word in search query individually?</p>

<pre><code># Fetch all pages and sort them alphabetically
queryset = Page.objects.all().filter(archived=False).order_by("title")

# Get search query if applicable
query = request.GET.get("q")
if query:
    queryset = queryset.filter(
        Q(title__icontains=query) |
        Q(content__icontains=query) |
        Q(user__username__icontains=query) |
        Q(user__first_name__icontains=query) |
        Q(user__last_name__icontains=query)
    ).distinct()
</code></pre>

<p>You're asking for something like the following, where you filter by each individual word in the query:</p>

<pre><code>import operator

queryset = Page.objects.all().filter(archived=False).order_by("title")

query = request.GET.get("q")
if query:
    words = query.split()
    fields = ["title__icontains", "content__icontains", "user__username__contains",
              "user__first_name__icontains", "user__last_name__icontains"]

    q_expression = [Q(f,w) for f in fields for w in words]
    queryset = queryset.filter(reduce(operator.or_, q_expression))\
                       .distinct()
</code></pre>

<p>However, at this point doing search this way gets a little bit messy. If your app grows and you need to search over several models, consider looking into an external search package such as <a href="http://haystacksearch.org/" rel="nofollow">Haystack</a>.</p>

python django search django-q