Joel
unread,Aug 15, 2018, 10:30:37 AM8/15/18Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to django...@googlegroups.com
I'm trying to write a search function for my model.
A customer has the following fields:
cstid = models.AutoField(primary_key=True, unique=True)
name = models.CharField(max_length=35)
age=models.IntegerField()
gender = models.CharField(max_length=10, default='')
mobile = models.CharField(max_length=15, default='')
email = models.CharField(max_length=50, default='')
address = models.CharField(max_length=80, default='')
city = models.CharField(max_length=25, default='')
My html form will submit the following data by POST via an ajax call to django:
var data = {
"name": name,
"age": age,
"email": email,
"address": address,
"phone": phone,
"city": city
};
data = $(this).serialize() + "&" + $.param(data);
These will be verified in the django view, and a search query
performed, as below:
def searchpat_for_docwise_appt (request):
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from django.db.models import CharField
from django.db.models.functions import Lower
CharField.register_lookup(Lower, "lower")
if request.method == 'POST':
name = request.POST.get('name')
age = request.POST.get('age')
# gender = request.POST.get('gender')
phone = request.POST.get('phone')
email = request.POST.get('email').lower()
address = request.POST.get('address')
city = request.POST.get('city')
if age.isdigit():
ANDSearchResult =
customer.objects.filter(name__lower__contains=name.lower(), age=age,
mobile__contains=phone, email__lower__contains=email.lower(
), address__lower__contains=address.lower(), city__lower__contains=city.lower())
else:
ANDSearchResult =
customer.objects.filter(name__lower__contains=name.lower(),
mobile__contains=phone, email__lower__contains=email.lower(
), address__lower__contains=address.lower(), city__lower__contains=city.lower())
if len(ANDSearchResult) < 1:
errmsg = 'No search results for AND search'
print("Error message is <%s>" % errmsg)
else:
print ("ANDSearchResult is <%s>" % ANDSearchResult)
errmsg = ''
if age.isdigit():
ORSearchResult = customer.objects.filter(
Q(name__lower__contains=name.lower()) | Q(age=age) | Q(
mobile__contains=phone) | Q(email__lower__contains=email.lower()) |
Q(address__lower__contains=address.lower()) |
Q(city__lower__contains=city.lower()))
else:
ORSearchResult = customer.objects.filter(
Q(name__lower__contains=name.lower()) | Q(
mobile__contains=phone) | Q(email__lower__contains=email.lower()) |
Q(address__lower__contains=address.lower()) |
Q(city__lower__contains=city.lower()))
if len(ORSearchResult) < 1:
errmsg = errmsg + 'No search results for OR search'
print("Error message is <%s>" % errmsg)
else:
print ("ORSearchResult is <%s>" % ORSearchResult)
print(errmsg)
return HttpResponse(errmsg)
else:
errmsg = 'No correct POST request. No valid response.'
print("Error message is <%s>" % errmsg)
return HttpResponse(errmsg)
As you can note above, I am doing two different queries
simultaneously. I want an AND operator like query where search has to
satisfy all input parameters. I also need an OR operator which should
provide a result if any of the fields matches the entered string for
the corresponding field. By this I mean that if a patient has a name
Jeff with age 56, and a patient Kane with age 23; and I enter jef in
the name field and 23 in the age field, both should be listed.
The problem arises when there are empty strings in the search boxes.
An OR search with an empty string gives all objects as results.
Obviously I dont want to return a patient record just because my
search strings are null.
Other than the long winded solution of checking for all combinations
of search queries like this:
if (name != '' and age != '' and phone != '' and email != '' and
address != '' and city != '':
ORSearchResult =
customer.objects.filter(Q(name__lower__contains=name.lower()) |
Q(age=age) | Q(mobile__contains=phone) |
Q(email__lower__contains=email.lower()) |
Q(address__lower__contains=address.lower()) |
Q(city__lower__contains=city.lower()))
elif (age != '' and phone != '' and email != '' and address != '' and
city != '':
ORSearchResult = customer.objects.filter(Q(age=age) |
Q(mobile__contains=phone) | Q(email__lower__contains=email.lower()) |
Q(address__lower__contains=address.lower()) |
Q(city__lower__contains=city.lower()))
elif (phone != '' and email != '' and address != '' and city != '':
ORSearchResult = customer.objects.filter(Q(mobile__contains=phone) |
Q(email__lower__contains=email.lower()) |
Q(address__lower__contains=address.lower()) |
Q(city__lower__contains=city.lower()))
.... Other permutations ...
What is a better solution?
An obvious idea that comes to mind is, to try to compile these filters
into a variable and pass it to the filter function. Am I on the right
track? How can I do this?