javascriptflaskwebformsurl-routingautosuggest

How to submit a form with autosuggest with Javascript and Python flask


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):

  1. Display items from autosuggest, when typing in a field in the webform
  2. Select an item from autosuggest and show the item in the field filled
  3. Fill other fields (without autosuggest)
  4. Hit submit button
  5. 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')

Solution

  • At the end, it was fairly simple. I just changed the routing as follows.

    @database.route('/database/result', methods=('GET', 'POST'))
    def database():
    

    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!