A Q object builds a Django ORM query condition that can be combined before it reaches .filter(). Ordinary filter clauses are AND-ed together; Q objects let a search match either condition with |, or compound conditions with &. section 12.4
Search first or last names
Split a musician search into terms, make a Q condition for first_name__istartswith and another for last_name__istartswith, then join them with |. Add later terms to the same query and pass the finished condition to Musician.objects.filter(q). A search for several terms therefore finds a name beginning with any term. section 12.4
Listing 12.6 A search view for musicians by their names
# RiffMates/bands/views.py
...
from django.db.models import Q
...
def search_musicians(request):
search_text = request.GET.get("search_text", "") #1
search_text = urllib.parse.unquote(search_text) #2
search_text = search_text.strip()
musicians = []
if search_text:
parts = search_text.split() #3
q = Q(first_name__istartswith=parts[0]) | \
Q(last_name__istartswith=parts[0]) #4
for part in parts[1:]: #5
q |= Q(first_name__istartswith=part) | \
Q(last_name__istartswith=part) #6
musicians = Musician.objects.filter(q) #7
data = {
"search_text": search_text,
"musicians": musicians,
}
return render(request, "search_musicians.html", data)
The view shows the complete path from query-string text through whitespace parsing and Q composition to filtered musician results. section 12.4
