I have a python/Flask site with a MySQL database containing tropes. I would like to create a form that will allow users to search the tropes for key words. This is what I have so far:
HTML form for submitting search:
<form action="/search_tropes" method="POST">
<label for="search_query">Search:</label>
<input type="text" class="form-control" id="search_query" aria-describedby="search_query_Help" name="search_query">
<button type="submit" class="btn btn-primary">Search</button>
</form>
This is the route for the search:
@app.route('/search_tropes', methods = ['POST'])
def searchQuery():
data = {
'search': request.form['search_query']
}
searched_tropes = Trope.searchTropes(data)
return render_template('search.html', searched_tropes = searched_tropes)
This is the class method for the search with the query:
@classmethod
def searchTropes(cls, data):
query = "SELECT * FROM tropes WHERE content LIKE %(search)s;"
results = connectToMySQL('htb_schema').query_db(query, data)
return results
This is currently working to search the database, but it will only return results that are an exact match, which is not very helpful. I would like to have it search for tropes that contain the search anywhere in the content column, which I know I can do using '%search%' in the query to allow characters before and after the search term; however, I am having trouble implementing this with the prepared statement to avoid SQL injections. This is what I have tried so far:
Modifying the data to insert the % around the form data:
data = {
'search': '%' + request.form['search_query'] + '%'
}
Which returns a Boolean result instead of the list of tropes.
I've also tried using Concat and another variable for the queries:
# query = "SET @search = %(search)s; SELECT * FROM tropes WHERE content LIKE CONCAT("%",@search,"%");"
# query = "SET @search = %(search)s; SELECT * FROM tropes WHERE content LIKE "%"+@search+"%";"
# query = "SELECT * FROM tropes WHERE content LIKE CONCAT('%', %(search)s, '%');"
# query = "SELECT * FROM tropes WHERE content LIKE CONCAT(%(search)s,"%");"
# query = "SELECT * FROM tropes WHERE content LIKE "%"+%(search)s+"%";"
But these also return a Boolean or I get the error: TypeError: not all arguments converted during string formatting.
Please let me know if you have any suggestions to make this search work, or if there is an easier/better method for searching the database for tropes with content that contains the search.
Edit: I just found out about FULLTEXT and using MATCH() and AGAINST() which has improved the situation, but it will only search for that word if it is isolated; searching for 'car' will return 'car accident' or 'buys a car' but will not return 'racecar' or 'cartoon'. I'm not sure if there is a way to add on to the FULLTEXT query to allow this.