yathomasi
yathomasi

Reputation: 548

Django append <queryset> for searching each words in a sentece using filter

I want to search each word in a sentence and put that in result['post'] dictionary and of course this code only looks for last query

queries = querystring.split()
    for query in queries:
        results['posts'] = Post.objects.filter(text__icontains=query)

i tried append,extend and a lot of things but it didn't work as expected.

Edit Update: I also tried

    count = {}
    results = {}
    post_results = []
    queries = querystring.split()
    for query in queries:
        post_results.append(Post.objects.filter(text__icontains=query))
    results['posts'] = post_results
    count['posts'] = results['posts'].count()

But this leads to another error count() takes exactly one argument (0 given)

Error Image

Also Post.objects.filter(text__icontains=query) this line returns a queryset value and Queryset type of django doesn't seem to have append. Is there it's own append like feature ? If so then that wouldn't change it's queryset type to list. Using temp variable like post_results = [] changes to list.

Can we change that list back to queryset? If we can then that would work.

Upvotes: 2

Views: 2142

Answers (4)

CoffeeBasedLifeform
CoffeeBasedLifeform

Reputation: 2921

How about this:

results = {'posts': []}
count = {'posts': []}
for query in querystring.split():
    qs = Post.objects.filter(text__icontains=query)
    results['posts'].append(qs)
    counts['posts'].append(qs.count())

Update after you answered your own question:
Oh, I was under the assumption you wanted a list of queries of each word with their respective result counts. If you only wanted to combine each string of the search term into an OR query you could use Q objects.

results = {}
count = {'posts': []}

from django.db.models import Q
qobjects = Q()
for query in querystring.split():     
    qobjects |= Q( ('text__icontains',query) )
 results['posts'] = Post.objects.filter(qobjects)
 counts['posts'] = results['posts'].count()

Upvotes: 1

Ali Akbar Afridi
Ali Akbar Afridi

Reputation: 880

instead of making multiple queries we can use Q object, here is the simple example

q = 'query string'
keywords = []
prevword = ""
for word in q.split(' '):
    prevword = prevword + word + " "
    keywords.append(prevword.lower())

query = Q(title__icontains=q)
for keyword in keywords:
    query.add(Q(title__icontains=keyword), Q.OR)

services = Service.objects.distinct().filter(query).all()

Upvotes: 1

yathomasi
yathomasi

Reputation: 548

Thanks all of you I tried everything mentioned at first and finally got a solution
I did a crazy thing at first.
I wanted to define an empty queryset so for results['posts'] so I did a bad but a working way
results['posts']=Post.objects.filter(text_icontains='sth_that_will_never_b_true')
and I used

Django Merge QuerySets

and solved the problem and then later studied genuine way to define empty QuerySet as

django.db.models.query.QuerySet.none

And gladly final code is

count = {}
results = {}
results['posts']=Post.objects.none() # empty QuerySet
queries = querystring.split()
for query in queries:
    results['posts'] = results['posts'] | Post.objects.filter(
        text__icontains=query)

count['posts'] = results['posts'].count()

Now everything works as expected.

Upvotes: 0

Damotorie
Damotorie

Reputation: 596

I guess the reason is results['posts'] value is overwritten per every for loop..

How about changing code like

queries = querystring.split()
tmp = []
for query in queries:
        tmp.append(Post.objects.filter(text__icontains=query))
results['posts'] = tmp

Upvotes: 1

Related Questions