I'm developing a Flask application that filters the values of a Mysql database table and based on the selected value of the first dropdown, it will update the value of the second dropdown. Finally return some data
Now the code is working but there seems to be a bug in the code such that when I make a new selection from the first dropdown it populates the second dropdown with the value of the first dropdown as well as the expected value The value of the second drop-down list
It shouldn't be doing this, I want it to only populate the second dropdown with the expected value, not add the first dropdown's value along with it.
This is my flask application code:
from flask import jsonify, request from flask import Flask, render_template import mysql.connector app = Flask(__name__) # Configure MySQL connection cnx = mysql.connector.connect( host="xxxxxxx", user="xxxxxxxxx", password="xxxxxxxxx", database="xxxxxxxxxx") @app.route('/', methods=['GET', 'POST']) def index(): try: cursor = cnx.cursor() query = "SELECT topic FROM text_table" cursor.execute(query) data = [row[0] for row in cursor.fetchall()] # Get the first column of all rows cursor.nextset() # consume any unread result cursor.close() if request.method == 'POST': selected_topic = request.form.get('selected_topic') # Get the selected topic from the form if selected_topic: cursor = cnx.cursor() query = "SELECT sub_topic FROM text_table WHERE topic = %s" cursor.execute(query, (selected_topic,)) sub_topics = [row[0] for row in cursor.fetchall()] # Get the sub topics for the selected topic cursor.nextset() selected_sub_topic = request.form.get('selected_sub_topic') # Get the selected sub topic from the form if selected_sub_topic: query = "SELECT text FROM text_table WHERE topic = %s AND sub_topic = %s" cursor.execute(query, (selected_topic, selected_sub_topic)) result = cursor.fetchone()[0] # Get the value of the text for the selected sub topic cursor.nextset() cursor.close() return render_template('index.html', topics=data, selected_topic=selected_topic, sub_topics=sub_topics, selected_sub_topic=selected_sub_topic, result=result) cursor.close() return render_template('index.html', topics=data, selected_topic=selected_topic, sub_topics=sub_topics) return render_template('index.html', topics=data) except Exception as e: # Return an error message if there's an exception return jsonify(error=str(e)), 500 if __name__ == '__main__': app.run()
This is my html code with a little JavaScript
<!DOCTYPE html> <html> <head> <title>Drop Down Filter</title> <script> function updateSubTopics() { var selectTopic = document.getElementById("selected_topic"); var selectSubTopic = document.getElementById("selected_sub_topic"); var selectedTopicValue = selectTopic.value; // Send a POST request to update the sub topic options var xhr = new XMLHttpRequest(); xhr.open('POST', '/'); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onload = function() { if (xhr.status === 200) { // Update the sub topic options selectSubTopic.innerHTML = xhr.responseText; // Check if the currently selected sub topic is valid for the new selected topic var subTopicOptions = selectSubTopic.options; var foundSelectedSubTopic = false; for (var i = 0; i < subTopicOptions.length; i++) { if (subTopicOptions[i].value === selectSubTopic.value) { foundSelectedSubTopic = true; break; } } if (!foundSelectedSubTopic) { selectSubTopic.value = ""; } } else { console.log('Request failed. Returned status of ' + xhr.status); } }; xhr.send('selected_topic=' + selectedTopicValue); } </script> </head> <body> <form method="POST"> <select name="selected_topic" id="selected_topic" onchange="updateSubTopics()"> {% for topic in topics %} <option value="{{ topic }}" {% if selected_topic == topic %}selected{% endif %}> {{ topic }} </option> {% endfor %} </select> <select name="selected_sub_topic" id="selected_sub_topic"> {% for sub_topic in sub_topics %} <option value="{{ sub_topic }}" {% if selected_sub_topic == sub_topic %}selected{% endif %}> {{ sub_topic }} </option> {% endfor %} </select> <input type="submit" value="Filter"> </form> {% if result %} <h1>{{ result }}</h1> {% endif %} </body> </html>
Thank you, any help would be greatly appreciated
P粉1410350892023-09-09 10:14:00
This issue occurs when you send a template response after filtering.
You have rendered index.html, but when changing the selection option from that row, you are also rendering index.html.
This basically means you paste all your html code into a select element which you can inspect by inspecting it in the browser.
In my opinion, what should be done is that you should only send a Python dictionary as the response of the child topic.
if selected_topic: cursor = cnx.cursor() query = "SELECT sub_topic FROM text_table WHERE topic = %s" cursor.execute(query, (selected_topic,)) sub_topics = [row[0] for row in cursor.fetchall()] # Get the sub topics for the selected topic cursor.nextset() selected_sub_topic = request.form.get('selected_sub_topic') # Get the selected sub topic from the form if selected_sub_topic: query = "SELECT text FROM text_table WHERE topic = %s AND sub_topic = %s" cursor.execute(query, (selected_topic, selected_sub_topic)) result = cursor.fetchone()[0] # Get the value of the text for the selected sub topic cursor.nextset() cursor.close() return render_template('index.html', topics=data, selected_topic=selected_topic, sub_topics=sub_topics, selected_sub_topic=selected_sub_topic, result=result) cursor.close() return sub_topics
After successfully obtaining the dictionary, the response will be formatted, so it needs to be parsed into json. You can then use JS loops to create the loop and append it to your sub_topic selection.
if (xhr.status === 200) { selectSubTopic.options.length = 0; var subTopicOptions = JSON.parse(xhr.responseText); for (var i = 0; i < subTopicOptions.length; i++) { var option = document.createElement('option'); option.text = subTopicOptions[i]; option.value = subTopicOptions[i]; selectSubTopic.appendChild(option); } // Check if the currently selected sub topic is valid for the new selected topic var subTopicOptions = selectSubTopic.options; var foundSelectedSubTopic = false; for (var i = 0; i < subTopicOptions.length; i++) { if (subTopicOptions[i].value === selectSubTopic.value) { foundSelectedSubTopic = true; break; } } if (!foundSelectedSubTopic) { selectSubTopic.value = ""; } } else { console.log('Request failed. Returned status of ' + xhr.status); }