1

I have the codes below that let users on my website to search for blogs. With the current, my HTML page will only show a list of data from all the row that has columns that match with the search input. But, I want to get the blog_id of all the matching rows that I just query with c.fetchall().

How would I do it? Should I write some codes right after I query data?... I would greatly appreciate if you help me. Also, if possible, could you show me how can I set the codes below to only query those rows that have a column that match the searching data? :

many_posts = BlogPost.query.order_by(BlogPost.date.desc()).paginate(page=page, per_page=10)
(These codes above are placed inside the "if request.method == 'POST':")

My codes (Python):

import os 
import _sqlite3

MYDIR = os.path.dirname(__file__)
SQLPATH = os.path.join(MYDIR, "..", "data.sqlite")
conn = _sqlite3.connect(SQLPATH, check_same_thread=False)  

c = conn.cursor()

@core.route('/', methods=['GET', 'POST'])
def index():
    # Call a function to later use in creating the template
    form = Blogsearch_form(request.form)

    if request.method == 'POST':
        c.execute("SELECT * FROM blog_post WHERE problem_name LIKE(?)", ('%' + str(form.search.data) + '%',))
        results = c.fetchall()
        page = request.args.get('page', 1, type=int)
        many_posts = BlogPost.query.order_by(BlogPost.date.desc()).paginate(page=page, per_page=10)
        return render_template('blog_search_result.html', results=results, many_posts=many_posts)



    page = request.args.get('page',1,type=int)
    many_posts = BlogPost.query.order_by(BlogPost.date.desc()).paginate(page=page, per_page=10)
    return render_template('index.html', many_posts=many_posts, form=form)

My codes of the BlogPost's database creation:

class BlogPost(db.Model):
    __tablename__ = 'blog_post'
    users = db.relationship(User)

    blog_id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer,db.ForeignKey('users.id'), nullable=False) #users.id  is taken from the tablename(users) and id in its table
    date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)  
    problem_name = db.Column(db.String(140), nullable=False)
    text = db.Column(db.Text, nullable=False)
    blog_image = db.Column(db.String(140), nullable=False, server_default='default_blog.jpg')


    def __init__(self, text, problem_name, user_id, blog_image):
        self.text = text
        self.problem_name = problem_name
        self.user_id = user_id
        self.blog_image = blog_image



    def __repr__(self):
        return f"Post ID: {self.post_id} -- Date:{self.date}---{self.problem_name}"

Part of my HTML codes:

    <h4>Search results:</h4>
    <h5>{{ results }}</h5>
   <p><small class="text-muted">If you see [ ] as the result, it means Upchanges have no relating problems to your search</small></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>


    </div>

{% endfor %}


Additionally, all of my current codes are working fine and showing no errors.

Upchanges
  • 310
  • 2
  • 14
  • 1
    to make it easier to help. Could you please add following information to your question. 1.) Show also the importsm that declare `db` to show us what python module you use for the ORM) Is this sqlalchemy? – gelonida May 19 '20 at 10:06
  • Yes, I'm using sqlalchemy sqlite and I use import sqlite3. And thank you so much for helping me!! – Upchanges May 19 '20 at 10:14
  • please post also a small html template file, that contains the bare minimum to show the problem. I think the issue might be in the template fole (the file, that we don't see) – gelonida May 19 '20 at 10:20
  • I just added it in my post. But you see, the reason why I want to query the blog_id of the rows I just query is because I want those blogs to be only related to the searching result. – Upchanges May 19 '20 at 10:22
  • Just to be sure. Is this what you are doing? `from flask_sqlalchemy import SQLAlchemy` and `app = Flask(__name__)` and `db = SQLAlchemy(app)` ? If yes it helps others to understand better your code if you add these lines to your code in the question. If no could you add the related lines? It just makes it easier to follow – gelonida May 19 '20 at 10:41
  • 1
    another question. Why do you once execute a direct sql query and afterwards you perform an SqlAlchemy query? Normally I'm used to applications that do either all queries by hand or use the ORM (SqlAlchemy) for almost everything. Is the reason, that you did not know how to filter with SqlAlchemy? (I never used SqlAlchemy, but if this is the case you might perhaps ask a separate question and then get rid of the direct sqlite query?) – gelonida May 19 '20 at 10:46
  • I adapted my answer. Is this what you want? – gelonida May 19 '20 at 10:52
  • Yes! I use from flask_sqlalchemy import SQLAlchemy and app = Flask(__name__) and db = SQLAlchemy(app). I'm not familiar with both query. Which type do you recommend if I'm using it to create a website? – Upchanges May 19 '20 at 11:21
  • 1
    the basic is plain sql queries. In any case it is good to play a little with them and to have some knowledge. 2 links as a potential starting point:https://www.tutorialspoint.com/sqlite/index.htm and https://www.guru99.com/sqlite-tutorial.html . An ORM (SqlAlchemy, Django-ORM, ...) is a kind of an abstraction and makes code more concise and often easier to understand (thoug sometimes less efficient), but its like a new language to learn. https://docs.sqlalchemy.org/en/13/orm/tutorial.html#querying shows you examples and you can click on sql to see corresponding sql – gelonida May 19 '20 at 11:46
  • Thank you!! Could you also please help me out in my comment down below? – Upchanges May 19 '20 at 11:47

2 Answers2

2

Not sure I understand. Do you mean something like.

c.execute("SELECT blog_id FROM blog_post WHERE problem_name LIKE(?)", ('%' + str(form.search.data) + '%',))
results = c.fetchall()
blog_ids = [entry[0] for entry in results]

gelonida
  • 5,327
  • 2
  • 23
  • 41
  • This works!!!! Thank you so so much!! Do you know any link for me to study about these kinds of querying sqlite database using Python? I wouldn't want to go here and ask questions every day, taking time from people :). P./s You are awesome!! – Upchanges May 19 '20 at 11:23
  • Oh, I forgot, now I have the blog_ids, is there any way for me to query them from my table BlogPost so that I can paginate them on my website? How could I put the blog_ids I just query into the codes : ````many_posts = BlogPost.query.order_by(BlogPost.date.desc()).paginate(page=page, per_page=10)```` or is there anyway for me to do the same thing in other way? – Upchanges May 19 '20 at 11:29
  • 1
    have to go back to work, but look at the section https://docs.sqlalchemy.org/en/13/orm/tutorial.html#querying you should get rid of the plain sql query and do everything with ORM (something like `query.filter(User.name.ilike('%ed%'))' or in your case BlogPost.query.filter(BlogPost.problem_name.like("%"+str(form.search.data) + '%').order_by(BlogPost.date.desc()).paginate(page=page, per_page=10)` but no time to test at the moment) – gelonida May 19 '20 at 11:52
  • Thank you! I will learn and fix this. Good luck with your work! – Upchanges May 19 '20 at 11:54
  • Kartikeya helped me out below with this code: `many_posts = BlogPost.query.filter(BlogPost.problem_name.ilike("%" + form.search.data + "%")).order_by(BlogPost.date.desc()).paginate(page=page, per_page=10)` and it works!! But thank you very much for sharing your materials and helping me a lot of times!! – Upchanges May 19 '20 at 14:08
  • Hi @gelonida! I have a new question and I would greatly appreciate if you could help me: https://stackoverflow.com/q/61904126/13097721 And thank you for helping me so many times!! (If this annoys you, please tell me and I will stop doing it. Please don't report me) – Upchanges May 20 '20 at 02:40
2

sorry to jump in late but if you want an sqlalchemy solution, then you should do something like below to get the list of ids:

id_list = [i[0] for i in BlogPost.query.with_entities(BlogPost.blog_id ).filter(BlogPost.problem_name.ilike("%" + form.search.data  + "%")).all()]

Also, I think for security reasons, you should use an ORM rather than the pure SQL Query!

gelonida
  • 5,327
  • 2
  • 23
  • 41
Kartikeya Sharma
  • 1,335
  • 1
  • 10
  • 22
  • Thank you! No, it's fine. We all are busy and I greatly appreciate for your help:) Do you recommend me using sqlalchemy over using pure SQL Query? – Upchanges May 19 '20 at 13:31
  • Also, if you have some free time. Could you help me with this similar one? So, now I have the list of ids, is there any way for me to query data that belong to those id from my table BlogPost so that I can paginate them on my website? How could I put the blog_ids I just query into the codes : many_posts = BlogPost.query.order_by(BlogPost.date.desc()).paginate(page=page, per_page=10) or is there anyway for me to do the same thing in other way? Thank you!! – Upchanges May 19 '20 at 13:34
  • 1
    just add this before order by ```.filter(BlogPost.problem_name.ilike("%" + form.search.data + "%"))``` – Kartikeya Sharma May 19 '20 at 13:59
  • Wow!!! Awesome!! It works!!! Thank you so much!!, I wish I could have give you some reputation. (but I can't with my level right now) :) – Upchanges May 19 '20 at 14:06
  • Umm.. Kartikeya, if I also want my column "text" to be filter together with my column "prolem_name", could I write `.filter(BlogPost.problem_name,text.ilike("%" + form.search.data + "%"))`? Thank you so much for helping me multiple times! – Upchanges May 19 '20 at 14:18
  • 1
    Depends if you are trying to do ```and``` or ```or``` filter. For example, if you want to do '''or'''. You can import ```from sqlalchemy import or_```. And then ```.filter(or_((BlogPost.problem_name.ilike("%" + form.search.data + "%")),(BlogPost.text.ilike("%" + form.search.data + "%")))``` – Kartikeya Sharma May 19 '20 at 14:30
  • Nice! So if I want to use and, I need to import and_. and just changed it with the location you put the or_ ? (Again, thank you so much for taking your time to help me!) – Upchanges May 19 '20 at 14:34
  • great. I never used SqlAlchemy and would have needed a little more time to set up a small test to validate the correct syntax / expressions. In an ideal world you would have worked with pure SQL queries to learn more about it's basic principles and only then switch to ORM, but being pragmatic and for your code, probably best to use ORM only. What can be interesting is (for debugging and learning to ask SqlAlchemy to display you the queries it constructed) I think this should be possible. At least it is possible with Django ORM. – gelonida May 19 '20 at 23:23
  • Hi Kartikeya! I have a new question and I would greatly appreciate if you could help me: https://stackoverflow.com/q/61904126/13097721 And thank you for helping me so many times!! (If this annoys you, please tell me and I will stop doing it. Please don't report me) – Upchanges May 20 '20 at 02:41