tyrrrr
asked on
django, python :: reduce() of empty sequence with no initial value
Hi
I am trying to add a search view to an application I wrote in django but my EntryManager() seems to be getting hung up on the last line of code when django tries to call the url of the search.
This EntryManager() (models.py) is excellent for performing searches in the django shell ($ python manage.py shell) like
x = Entry.objects.search('spam ')
list(x)
for example
However when I attempt to visit the url of the search I am met with the error " reduce() of empty sequence with no initial value " and a reference to the last line of EntryManager()
return qs.filter(reduce(operator. or_, q_objects))
I use this method to strip multiple word queries and place underscores between the words
type error:
reduce() of empty sequence with no initial value
The problems seems to be that the EntryManager() requires a string from the beginning and I haven't been able to make it work without one.
The rest of my code works perfectly.
Obviously the value will be empty before a query is made. What am I doing wrong? Is there perhaps a better way to connect my search view to this object?
I am trying to add a search view to an application I wrote in django but my EntryManager() seems to be getting hung up on the last line of code when django tries to call the url of the search.
This EntryManager() (models.py) is excellent for performing searches in the django shell ($ python manage.py shell) like
x = Entry.objects.search('spam
list(x)
for example
However when I attempt to visit the url of the search I am met with the error " reduce() of empty sequence with no initial value " and a reference to the last line of EntryManager()
return qs.filter(reduce(operator.
I use this method to strip multiple word queries and place underscores between the words
type error:
reduce() of empty sequence with no initial value
The problems seems to be that the EntryManager() requires a string from the beginning and I haven't been able to make it work without one.
The rest of my code works perfectly.
Obviously the value will be empty before a query is made. What am I doing wrong? Is there perhaps a better way to connect my search view to this object?
//////////////////////
models.py
import operator
from django.db import models
from django.db.models import Q
class EntryManager(models.Manager):
def search(self, search_terms):
terms = [term.strip() for term in search_terms.split()]
q_objects = []
for term in terms:
q_objects.append(Q(name__icontains=term))
q_objects.append(Q(description__icontains=term))
qs = self.get_query_set()
return qs.filter(reduce(operator.or_, q_objects))
//////////////////////
views.py
def searching(request):
query_string = ''
if ('q' in request.GET) and request.GET['q'].strip():
query_string = request.GET['q'].strip()
results = Entry.objects.search(query_string)
return render_to_response("search_results.html", {'query_string': query_string, 'results' : results})
//////////////////////
search_results.html
<div>Searched Results</div>
{%if results%}
{% for e in results%}
<a href=../{{e.slug}}>{{e.name}}</a></div>
{% endfor %}
{% else %} Nothing to see here...
{% endif %}
//////////////////////
That tells you q_objects is empty. Were you expecting that?
ASKER
I know that it will be empty before a query is made but I am unsure how to circumvent the reduce() object in the case that there is no q.
I have been advised to simply return qs.all() or qs.none() instead of qs.filter() in this case but I am not exactly sure how to implement this.
I have been advised to simply return qs.all() or qs.none() instead of qs.filter() in this case but I am not exactly sure how to implement this.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Have a look at http://docs.python.org/library/functions.html#reduce
If you do not know what is inside the sequence, you can also get the empty sequence. Use the third argument of the reduce(). The doc says
"If the optional initializer is present, it is placed before the items of the
iterable in the calculation, and serves as a default when the iterable
is empty."
If you do not know what is inside the sequence, you can also get the empty sequence. Use the third argument of the reduce(). The doc says
"If the optional initializer is present, it is placed before the items of the
iterable in the calculation, and serves as a default when the iterable
is empty."
ASKER
The initializer has to be an integer though. How can this be used in the case of something that is being used to reduce unicode strings?
The documentation shows only the example. The initializer could be of any type that is expected by the function passed to reduce. Try the separate Python sample below. If you remove the u'' initializer (empty unicode string) from the bottom line, you get the following error:
Traceback (most recent call last):
File "C:\tmp\___python\tyrrrr\a .py", line 13, in <module>
result = reduce(greater, lst)
TypeError: reduce() of empty sequence with no initial value
If you put the initializer there, the result will contain the empty string (or whatever string that you put as the initializer).
Traceback (most recent call last):
File "C:\tmp\___python\tyrrrr\a
result = reduce(greater, lst)
TypeError: reduce() of empty sequence with no initial value
If you put the initializer there, the result will contain the empty string (or whatever string that you put as the initializer).
def greater(a, b):
if a > b:
return a
else:
return b
lst = [ u'aaa', u'bbb', u'ccc']
result = reduce(greater, lst)
print result
lst = []
result = reduce(greater, lst, u'')
print result
ASKER
This is the final solution. Note that qs must be defined before it is referenced.
Thanks everyone!
Thanks everyone!
class EntryManager(models.Manager):
def search(self, search_terms):
terms = [term.strip() for term in search_terms.split()]
qs = Entry.objects.all()
if terms:
q_objects = []
for term in terms:
q_objects.append(Q(name__icontains=term))
q_objects.append(Q(description__icontains=term))
qs = self.get_query_set()
return qs.filter(reduce(operator.or_, q_objects))
return qs.none() #or qs.all() as the case may be
ASKER
Thank you! Your insight was very helpful in solving the problem.
ASKER
reduce() of empty sequence with no initial value
This is the error:
Request Method: GET
Request URL: http://dsfffffffffffffffffffff/search/
Exception Type: TypeError
Exception Value: reduce() of empty sequence with no initial value
Exception Location: /dsfffffffffffffffffffff/m
views.py in searching
68. results = Entry.objects.search(query
models.py in search
59. return qs.filter(reduce(operator.