i have a django app that retrieve all subjects from a single table of users. i've also implemented an input search form, this is the query performed:
all_soggs = Entity.objects.filter(lastname__istartswith=request.GET['query_term']).order_by('lastname')
if(all_soggs.count()==0):
all_soggs = Entity.objects.filter(firstname__istartswith=request.GET['query_term']).order_by('firstname')
as you can see the query first search for matching items by lastname, and then by firstname. this works until i insert the complete name 'firstaname lastname' or 'lastname firstname', in this case there's no results. how can i modify the query to make a better search?
thanks - luke
With the Django QuerySet class, you can apply filters that return QuerySets defined by your filters. The filter() method returns all objects that match the keyword arguments given to the method.
Definition and Usage The contains lookup is used to get records that contains a specified value. The contains lookup is case sensitive. For a case insensitive search, use the icontains lookup.
values() Returns a QuerySet that returns dictionaries, rather than model instances, when used as an iterable. Each of those dictionaries represents an object, with the keys corresponding to the attribute names of model objects.
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:
Entity.objects.filter(
Q(first_name__istartswith="Firstname") | Q(last_name__istartswith="Firstname") |
Q(first_name__istartswith="Lastname") | Q(last_name__istartswith="Lastname")
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With