I use Python Flask and Javascript (jQuery) to create a simple web form with autosuggest (from external API). My code works partially, but I am struggling with the routing/functions in Flask and autosuggest in Javascript. The current code below shows the items from the autosuggest. I can select an item, as well as filling the other fields in the webform, but when submitting the form, it returns JSON file of the autosuggest items. I don’t know how to pass the result of one function to the other function. I expect to be able to do the following in the same HTML page (single page application):
- Display items from autosuggest, when typing in a field in the webform
- Select an item from autosuggest and show the item in the field filled
- Fill other fields (without autosuggest)
- Hit submit button
- See the query results page (detail not described in this question)
Can somebody help me? Minimal change is preferred, but, if it is better to refactor the code structure, that is also fine. Many thanks!
mainapp/templates/layout.html
<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<!-- <script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script> -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js" crossorigin="anonymous"></script>
<script>
$(function() {
$("#project").autocomplete({
source: function(request, response) {
console.log(request.term);
$.ajax({
type: "POST",
url: "http://127.0.0.1:5000/database",
dataType: "json",
cache: false,
data: {
entity_type: request.term
},
success: function(data) {
console.log(data);
response(data);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus + " " + errorThrown);
}
});
},
minLength: 2,
focus: function(event, ui) {
$("#project").val(ui.item.name);
return false;
},
select: function(event, ui) {
$("#project").val(ui.item.label);
$(event.target).val(ui.item.id); // Set the input value to the selected item's name
return false;
}
})
.autocomplete("instance")._renderItem = function(ul, item) {
return $("<li>")
.append("<div><b>" + item.id + ":" + item.name + "</b>" + " " + item.description + "</div>")
.appendTo(ul);
};
});
mainapp/templates/database.html
<form method="post" id="search-form">
<label for="entity_type">Please specify an entity type </label>
<input type="text"
name="entity_type"
id="project"
size="150"
placeholder="Specify entity type here (e.g. Q5)"
value="{{ request.form['entity_type'] }}"></input>
<label for="country">Please specify a country</label>
<input type="text"
name="country"
size="50"
placeholder="Specify a country (e.g. Netherlands)"
value="{{ request.form['country'] }}"></input>
<button type="submit">Search</button>
</form>
database/views.py
@database.route('/database/')
def upload_form():
return render_template('database.html')
@database.route('/database/', methods=('GET', 'POST'))
# This is the autosuggest function
def autosuggest():
term = request.form['entity_type']
print ('term: ', term)
json_url = f'https://wikidata.reconci.link/en/suggest/entity?prefix={term}'
headers = ''
r = requests.get(json_url, headers=headers, timeout=3)
json_data = r.json()
json_data = json_data['result']
resp = jsonify(json_data)
resp.status_code = 200
return resp
# This is the main function of the webform which tries to use the selected item from the autosuggest function. The webform also contains input fields without autosuggest.
@database.route('/database/', methods=('GET', 'POST'))
def database():
if request.method == 'POST':
# I don't know how to pass the selected item from autosuggest function in here. 1st variable is for autosuggest, the 2nd one is without it
entity_type = autosuggest()
country = request.form['country']
# More code here #
return render_template('database.html', total_results=total_results, messages2=messages2, messages3=messages3, input=input)
else:
render_template('database.html')
return render_template('database.html')
2
Answers
At the end, it was fairly simple. I just changed the routing as follows.
As suggested, I also started to create different URLs for different functions/pages: search page
/search
search result page/search/result
,/search/autosuggest1
,/search/autosuggest2
etc Thanks!When the browser makes a POST request to
/database/
which route do you expect it to run?This one?
or this one?
You want it to run the first one for the Ajax request and the second one for the form submission but you’ve given the two routes the same URL and method.
You need different URLs for the different things you are requesting!