2

I have these codes below:

many_posts = BlogPost.query.filter(or_((BlogPost.problem_name.ilike("%" + form.search.data + "%")),(BlogPost.text.ilike("%" + form.search.data + "%")))).order_by(BlogPost.date.desc()).paginate(page=page, per_page=10)

return render_template('blog_search_result.html', id_list=id_list, many_posts=many_posts, no_posts=no_posts)

It's an sqlalchemy query command and it let users on my website to search/filter and query blogs. But sometimes, the input they give is not in the database and my website will not show anything. So, instead of not showing anything, I want to show a text says: "Couldn't find relating things to your search". I wonder if there is any "if statement" Python/Sqlalchemy codes I can use to identify if my query command didn't find any information and then to show the quote above. Something like:

        if many_posts is null:
            no_posts= "Couldn't find relating problems with your search"

Part of my HTML codes that connect with many_posts:

    <h4>Search results<span class="iconify" data-icon="icons8:search" data-inline="false"></span>:</h4>
    <p>{{ no_posts }}</p>


<div class="container row row-cols-1 row-cols-md-2 text-center">
{% for post in many_posts.items%}

    <div class="card border-dark mb-3 " style="width: 20rem;">
     <div class="card-body ">
         <h7><a class="text-warning" href="{{ url_for('users.user_posts', username=post.creator.first_name+post.creator.middle_name+post.creator.last_name) }}"><img class="text-center rounded" src="{{ url_for('static', filename='profile_pics/'+ post.creator.profile_image) }}" width = "35" height = "35" alt=""> {{ post.creator.first_name}} {{ post.creator.middle_name }} {{ post.creator.last_name }}</a></h7>
         <p></p>
         <img class="text-center rounded responsive1" alt="" src="{{ url_for('static', filename='blog_pics/'+ post.blog_image) }}" width = "495" height = "250">
         {# Need caution for post.blog_image on the code above #}
         <p></p>
         <h2><a class="card-tittle text-body problem" href="{{ url_for('blog_posts.blog_view', blog_validated_id=post.blog_id) }}">{{ post.problem_name[0:40]}}..</a></h2>
         <p class="card-text">{{ post.text[0:100] }}</p>
         <p><small class="text-muted">Posted on: {{ post.date.strftime('%Y-%m-%d') }}</small></p>
         <a class="btn btn-warning" href="{{ url_for('blog_posts.blog_view', blog_validated_id=post.blog_id) }}">Read more</a>
     </div>

I'm a beginner in coding and I would greatly appreciate if you could help me. Thank you!

========================Answers/Solution=========================

I use the codes below:

Method 1:

 many_posts0 = BlogPost.query.filter(or_((BlogPost.problem_name.ilike("%" + form.search.data + "%")),(BlogPost.text.ilike("%" + form.search.data + "%")))).order_by(BlogPost.date.desc())

        many_posts = many_posts0.paginate(page=page, per_page=10)
        num_posts = many_posts0.count()
        if num_posts == 0:
            no_posts="Couldn't find relating problems"
        else:
            no_posts=''

return render_template('blog_search_result.html', id_list=id_list, many_posts=many_posts, num_posts=num_posts, no_posts=no_posts)

In HTML, I use:

<p>{{no_posts}}</p>

Method 2:

many_posts = BlogPost.query.filter(or_((BlogPost.problem_name.ilike("%" + form.search.data + "%")),(BlogPost.text.ilike("%" + form.search.data + "%")))).order_by(BlogPost.date.desc()) 
no_posts = ''

if not many_posts.first():
   no_posts= "Couldn't find relating problems with your search"
many_posts = many_posts.paginate(page=page, per_page=10)

Upchanges
  • 310
  • 2
  • 14

3 Answers3

1

Not sure, but you might try two things:

Perhaps the result of a query doesn't evaluate to False if no row is returned. an empty list evaluates to False, but query results are probably objects of a different type and might not evaluate to False. converting to a list might help.

return render_template('blog_search_result.html', id_list=id_list, posts=list(posts))

for debugging purposes. you could have added following. Printing / logging is quite helpful to understand

print("Posts is ", posts, "and as bool it returns ", bool(posts))
return render_template('blog_search_result.html', id_list=id_list, posts=list(posts))

After first feedback

OK the output of SqlAlchemy paginate() is not iterable. (Did you try to read the doc of paginate. It might mention whether there is some info about amount of results)

Following might work with SqlAlchemy (I don't have time to try)

posts_to_show = BlogPost.query.filter(or_((BlogPost.problem_name.ilike("%" + form.search.data + "%")),(BlogPost.text.ilike("%" + form.search.data + "%")))).order_by(BlogPost.date.desc())

post_page = posts_to_show.paginate(page=page, per_page=10)

num_posts = posts.count()  # there might be something better to find out if there is at least one post, but I don't know it

return render_template('blog_search_result.html', id_list=id_list, posts=posts_page, num_posts=num_posts)
gelonida
  • 5,327
  • 2
  • 23
  • 41
  • Hi! Thank you for helping me again :) I tried render_template with list(posts) or in my case, list(many_posts) but my website will show this error : "TypeError: 'Pagination' object is not iterable." I think the reason behind this is because I'm paginating them... But I'm trying to use bool() now – Upchanges May 20 '20 at 09:58
  • Oh, and do you think if there is any way to count the query result. Maybe I can do like if the number of query results is 0, do this:.... ? – Upchanges May 20 '20 at 10:03
  • you're right. the pagination object is the issue. I will add something in my answer, but busy at the moment and as I'm not a big sqlalchemy expert I don't know if it behaves the same way as the django orm that I know – gelonida May 20 '20 at 10:14
  • This helped me to count the number of posts/ rows I just query and show it to the users! Thank you so much!! – Upchanges May 20 '20 at 13:20
  • Eventually, this helped me to fix my problem. Thank you! – Upchanges May 20 '20 at 13:43
  • oops just saw now, that you added the solution alerady to your question. That's perfect – gelonida May 20 '20 at 21:46
  • Hi @gelonida, I just had a new question and I would greatly appreciate if you could help me with it: https://stackoverflow.com/questions/62230718/how-can-i-query-and-get-data-from-my-sqlite-database-even-when-my-search-input-h – Upchanges Jun 06 '20 at 12:13
1

There are many ways to do what you are trying to accomplish here! You can check if there is no data in your query like this:

many_posts = BlogPost.query.filter(or_((BlogPost.problem_name.ilike("%" + form.search.data + "%")),(BlogPost.text.ilike("%" + form.search.data + "%")))).order_by(BlogPost.date.desc()) #without paginate
no_posts = None
#check if doesn't have anything inside 
if not many_posts.scalar():
   no_posts= "Couldn't find relating problems with your search"
many_posts = many_posts.paginate(page=page, per_page=10)

You can read more about scalar() here.

Kartikeya Sharma
  • 1,335
  • 1
  • 10
  • 22
  • Thank you!! This absolutely works!! :) And thank you for helping me multiple times!! – Upchanges May 20 '20 at 13:17
  • Umm.., but Kartikeya, the many_post.scalar() could only query 1 row in my database, it causes this error when I run my website: "sqlalchemy.orm.exc.MultipleResultsFound: Multiple rows were found for one()" Could you please teach me how to fix this? Thank you! – Upchanges May 20 '20 at 13:28
  • Hi Kartikeya! I used @gelonida's methods and it worked. So I don't have trace now... But after I did some research, I found out that scalar() could only return the first element of the first result or return none... So I think we couldn't use scalar() in this case. But thank you so much for helping me many times! – Upchanges May 20 '20 at 13:43
  • try using ```.first()``` instead ```.scalar()``` – Kartikeya Sharma May 20 '20 at 14:00
  • Yes! Thank you Kartikeya and gelonida! I just added first to my answers/ solution in my post. – Upchanges May 21 '20 at 00:35
  • Hi @Kartikeya, I just had a new question and I would greatly appreciate if you could help me with it: https://stackoverflow.com/questions/62230718/how-can-i-query-and-get-data-from-my-sqlite-database-even-when-my-search-input-h – Upchanges Jun 06 '20 at 12:13
  • Hi @KartikeyaSharma! Thank you so much for helping me multiple times! I would greatly appreciate if you could help me with other new problems of mine: stackoverflow.com/q/62373393/13097721 (And please don't report me if this annoys you... Just tell me and I will stop doing this.) – Upchanges Jun 14 '20 at 13:54
0

You need not operator in if condition:

if not <variable>:
    #block_code

And you don't need to declare or pass no_posts to render_template. You can achieve your desired result by doing something this just in your jinja code html template only.

foobar.py

posts = BlogPost.query.filter(or_((BlogPost.problem_name.ilike("%" + form.search.data + "%")),(BlogPost.text.ilike("%" + form.search.data + "%")))).order_by(BlogPost.date.desc()).paginate(page=page, per_page=10)

return render_template('blog_search_result.html', id_list=id_list, posts=posts)

blog_search_result.html

<h4>Search results<span class="iconify" data-icon="icons8:search" data-inline="false"></span>:</h4>
{% if not posts %}
   <p> Couldn't find relating problems with your search </p>
{% else %}
  <div class="container row row-cols-1 row-cols-md-2 text-center">
  {% for post in posts.items %}
    <div class="card border-dark mb-3 " style="width: 20rem;">
     <div class="card-body ">
         <h7><a class="text-warning" href="{{ url_for('users.user_posts', username=post.creator.first_name+post.creator.middle_name+post.creator.last_name) }}"><img class="text-center rounded" src="{{ url_for('static', filename='profile_pics/'+ post.creator.profile_image) }}" width = "35" height = "35" alt=""> {{ post.creator.first_name}} {{ post.creator.middle_name }} {{ post.creator.last_name }}</a></h7>
         <p></p>
         <img class="text-center rounded responsive1" alt="" src="{{ url_for('static', filename='blog_pics/'+ post.blog_image) }}" width = "495" height = "250">
         {# Need caution for post.blog_image on the code above #}
         <p></p>
         <h2><a class="card-tittle text-body problem" href="{{ url_for('blog_posts.blog_view', blog_validated_id=post.blog_id) }}">{{ post.problem_name[0:40]}}..</a></h2>
         <p class="card-text">{{ post.text[0:100] }}</p>
         <p><small class="text-muted">Posted on: {{ post.date.strftime('%Y-%m-%d') }}</small></p>
         <a class="btn btn-warning" href="{{ url_for('blog_posts.blog_view', blog_validated_id=post.blog_id) }}">Read more</a>
     </div>
    </div>
  {% endfor %}
  </div>
{% endif %}
Pratik149
  • 1,109
  • 1
  • 9
  • 16
  • Hi Pratik149! Thank you so much for helping me! So I tried {% if not many_posts %} and have a

    Couldn't find relating problems with your search

    down below. But when I search for something I know that is not in the database, my HTML web page still don't show that "Couldn' find..." text.
    – Upchanges May 20 '20 at 04:36
  • @Upchanges I don't exactly know how your complete html code looks, so I can't correct you there, but just make sure you are putting {% else %} and {% endif %} at right places. FYI I added some extra div tags in above answer code so as to complete the code blocks. – Pratik149 May 20 '20 at 04:56
  • Hi Pratik, so I copy your entire code, and only change posts to many_posts just like my original codes. But well, it's still not working... – Upchanges May 20 '20 at 05:14
  • Instead of {% if not many_posts %} try putting {% if many_posts is None %}. Both yields the same purpose but still try it. – Pratik149 May 20 '20 at 05:19
  • Hi Pratik149! Thank you for helping me! I tried that but it is still not working... – Upchanges May 20 '20 at 09:59
  • 1
    Possibly your database consists some value with empty string or spaces (which is not null or None) and it is returning it when you query in your BlogPost model. Try printing posts variable just before you return it to render_template function, and check whether it is actually null or does it consists some empty strings. – Pratik149 May 20 '20 at 10:28
  • 2
    agreed add `print` statements of all variables, that you pass to `render_template` and post the output for the scenario where you have issues – gelonida May 20 '20 at 11:03
  • Thank you Pratik and gelonida!! I will surely try those methods before I come here and ask you :) Also, thank you to both of you for helping me many times!! – Upchanges May 20 '20 at 13:20
  • Hi @Pratik149! Thank you so much for helping me multiple times! I would greatly appreciate if you could help me with my new problems: stackoverflow.com/q/62373393/13097721 (And please don't report me if this annoys you... Just tell me and I will stop doing this.) – Upchanges Jun 14 '20 at 13:54
  • @Upchanges I just got the notification. I checked your question, and saw that gelonida already helped you in solving the problem, which is cool. And talking about the downvote on your question, I upvoted again to make it neutral, but next time make sure you keep a note of geolonida's point. :) – Pratik149 Jun 15 '20 at 12:24
  • Thank you @Pratik149!! That's very kind of you!! I really appreciate the upvote and will keep @gelonida's point in mind :) – Upchanges Jun 15 '20 at 13:36