Trying to use oninput event with python flask

117 Views Asked by At

I'm trying to make a program using html and python flask. In this program I have a list of data and a search field where the user can search thru their data. I would like that as soon as the user starts typing, I can take what he has typed and save it to a variable. The problem is happening in the oninput, it seems that it is not working correctly. I don't get eny erros, it simply doesn't do the python code.

This is my html code:

<form class="d-flex" role="search">
    <input oninput="{{ url_for( 'search') }}" type="search" name="search" placeholder="Search" aria-label="Search">
</form>

And this is my python code:

from flask import Flask, render_template, request

@app.route('/search', methods=['POST', 'GET'])
def search():
    # the program is never getting to this part
    users_input = request.form['search']
    return render_template('index.html')

Is there any way I can make this work?

Thanks!

1

There are 1 best solutions below

0
On BEST ANSWER

The input event is not suitable for passing a URL in order to send the data automatically. This is a JavaScript event for which a function must be registered as a handler in order to react to the event. The work of sending the data thus remains with the developer.

First, however, you should decide whether your data requires a transfer using a GET or POST request.

With a GET request, the form data is sent after a '?', separated by '&' within the URL. These can be extracted on the server side using request.args. This is the usual procedure for a search query.

However, if you use a POST request, the form data is sent within the request body and can be queried via request.form. The request data is better protected from the eyes of third parties and is not limited in size.

Below is a simple example that you can adapt to your needs. The form's data is sent via AJAX through the Fetch API and the server's response is inserted into the page.

Python Flask
from flask import (
    Flask, 
    render_template, 
    request
)

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

# Define the required request-methods here.
@app.route('/search', methods=['GET']) 
def search():
    # Use request.args.get('search', '') for a GET request
    # or request.form.get('search', '') for a POST request.
    user_input = request.args.get('search', '')
    return render_template('results.html', **locals())
HTML (./templates/index.html)
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Index</title>
</head>
<body>
    <form onsubmit="handleSubmit(event)">
        <input type="search" name="search" oninput="handleInput(event)" />
    </form>

    <div id="results"></div>

    <script type="text/javascript">
        function handleInput(event) {
            const submitEvent = new SubmitEvent('submit', { submitter: event.target });
            event.target.form.dispatchEvent(submitEvent);
        }
        function handleSubmit(event) {
            event.preventDefault();
            const url = {{ url_for('search') | tojson }};

            /* If you use a GET request. */
            const formData = new FormData(event.target);
            const params = Array.from(formData.keys(), key => {
                return `${encodeURIComponent(key)}=${encodeURIComponent(formData.get(key))}`;
            }).join('&');
            
            fetch(`${url}?${params}`)
                .then(resp => resp.ok && resp.text())
                .then(text => {
                    const elem = document.getElementById('results');
                    elem && (elem.innerHTML = text);
                });

            /* If you use a POST request. */
            // fetch(url, {
            //  method: 'POST', 
            //  body: new FormData(event.target)
            // })
            //  .then(resp => resp.ok && resp.text())
            //  .then(text => {
            //      const elem = document.getElementById('results');
            //      elem && (elem.innerHTML = text);
            //  });
        };
    </script>
</body>
</html>
HTML (./templates/results.html)
<p>Your results for "{{user_input}}" here!</p>