[Fixed]-Django queryset – searching for firstname and lastname


Copy/paste from: https://stackoverflow.com/a/17361729/1297812

from django.db.models import Q 

def find_user_by_name(query_name):
   qs = User.objects.all()
   for term in query_name.split():
     qs = qs.filter( Q(first_name__icontains = term) | Q(last_name__icontains = term))
   return qs


You need Q objects and you also need to split your query into separate terms (since no first name will match the full string “Firstname Lastname”).

Here’s an idea to match any first or last name starting with either “Firstname” or “Lastname” in the search “Firstname Lastname”.

This is a generic search – adjust the query to suit your specific needs!

Edit: oops, I really don’t like using reduce since it looks confusing, but these need to be ORed together and we can’t do a more verbose version because the number of terms is unknown.

import operator
from django.db.models import Q

search_args = []
for term in request.GET['query_term'].split():
    for query in ('first_name__istartswith', 'last_name__istartswith'):
        search_args.append(Q(**{query: term}))

all_soggs = Entity.objects.filter(reduce(operator.or_, search_args))

To clarify how to use Q objects, given the search “Firstname Lastname” the previous query is equal to:

    Q(first_name__istartswith="Firstname") | Q(last_name__istartswith="Firstname") |
    Q(first_name__istartswith="Lastname") | Q(last_name__istartswith="Lastname")


This is a fairly old question but I just ran into the same problem and I thought I would share a more elegant solution.

from django.db.models import Value as V
from django.db.models.functions import Concat

from ..models import User

def find_user_by_name(search_str) -> QuerySey[User]:
    q = User.objects.annotate(full_name=Concat('first_name', V(' '), 'last_name'))
    q = q.filter(full_name__icontains=search_str)
    return q

This is the only solution that I have found which lets gives the behaviour I wanted, IE seaching with a full name string with a space ("John Doe") and with a partial string ("John Do").


Similar question:Querying full name in Django

query = request.GET.get('query')
entities = []

    firstname = query.split(' ')[0]
    lastname  = query.split(' ')[1]
    entities += Entity.objects.filter(firstname__icontains=firstname,lastname__icontains=lastname)
    entities += Entity.objects.filter(firstname__icontains=lastname,lastname__icontains=firstname)

entities = set(entities)

Leave a comment