Smitty
Smitty

Reputation: 165

Flask: How can I pass values from for loop to html with AJAX?

I'm making a web app that checks to see if a user exist at various forums, then returns the results dynamically on web page via AJAX.

I'm using flask, which calls on the original python script.

main.py:

app = Flask(__name__)


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


@app.route('/', methods=['POST'])
def search_form():

    x = request.form['searchinput']

    a = Vbulletin(x)

    def result_gen():
        return a.reg_ver()
    result_gen()

    for s in result_gen():
        text = s


    return render_template("index.html", text=text)


if __name__ == "__main__":
    app.run(debug=True)

the variable text is what i would like to dynamically display in Html as each response comes in. The way my code is written now it only displays the last item.

AJAX:

$(document).ready(function() {

    $('form').on('submit', function(event) {

        $.ajax({
            data : {
                x : $('#searchInput').val(),
            },
            type : 'POST',
            url : '/'
        })
        event.preventDefault();
    });
});

index.html:

<!DOCTYPE html>
<html>
    <head>
        <title>UserFind Home</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
        <link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}">
         <script type="text/javascript" src="{{url_for('static', filename='forumsearch.js')}}"></script>
    </head>
    <body>
        <nav>
            <ul id="navlist">
                <h1>Userfind</h1>
                <li><a class="btn" href="#home">Home</a></li>
                <li><a class="btn" href="#contact">Contact</a></li>
                <li><a class="btn" href="#about">About</a></li>
                <form method="POST" name=searchbar>
                    <ul id="navsearch">
                        <li class="search">
                            <input type="text" id="searchinput" name="searchinput" placeholder="Search for User here. Must be atleast 5 characters long.">
                        </li>
                        <li><button type="submit" class="btn-default">Submit</button></li>
                    </ul>
                </form>
            </ul>
        </nav>
        <script>

            var btnContainer = document.getElementById("navlist");
            var btns = btnContainer.getElementsByClassName("btn");

            for (var i = 0; i < btns.length; i++) {
            btns[i].addEventListener("click", function() {
            var current = document.getElementsByClassName("active");

            if (current.length > 0) {
            current[0].className = current[0].className.replace(" active", "");
            }
            this.className += " active";
                });
            } 
            </script>

        <p>{{ text }}</p>

        <div class="footer">
            <p>&copy;2019 Userfind</p>
          </div>
    </body>
</html>

I've found a lot of information on how to pass a single value( or multiple values one time), but how can I pass each value from flask to html dynamically as a response is received?

Edit: This is the code that gets called with a.reg_ver():

    def reg_ver(self):

        urlfile = json.load(open("/home/vbulletin_regversion_SHORT_TESTING_dict.txt"))
        for url, url_veri in urlfile.items():
            try:
                payload = {'username': self.name, 'securitytoken': 'guest', 'do': 'verifyusername'}
                headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0'}

                s = requests.Session()
                s.get(url, headers=headers)
                response = s.post(url_veri, headers=headers, data=payload)
                soup = BeautifulSoup(response.text, "html.parser")
                message = soup.find('message').text
                if self.name in message:
                    result = (url, "user found!!! I SAID USER FOUND!!!")
                    yield result
                elif message == "Username is valid and not in use.":
                    result = (url, "user not found")
                    yield result
                else:
                    result = (message, "possible error")
                    yield result

The code checks for a user from a forum in the list, then yields the result. I pass result to flask with this:

def result_gen():
    return a.reg_ver()
result_gen()

for s in result_gen():
    text = s

Can I append to a temporary list, and dynamically add each result to html, or am I going about this the wrong way?

Upvotes: 0

Views: 2133

Answers (1)

furas
furas

Reputation: 142641

Flask should send only text (or JSON) on AJAX requests and AJAX should get text (without HTML) and append() to HTML which is already in browser. So this way it can appends new line to existing text.

Working example:

from flask import Flask, render_template_string, request

app = Flask(__name__)

@app.route('/')
def index():
    return render_template_string('''
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    </head>
    <body>
        <form method="POST">
            <input type="text" id="searchinput" name="searchinput">
            <button type="submit">Submit</button>
        </form>
        <p></p>
        <script>
        $(document).ready(function() {
            $('form').on('submit', function(event) {
                $.ajax({
                    data: {x: $('#searchinput').val()},
                    type: 'POST',
                    url: '/',                    
                }).done(function(data){
                    $('p').append(data+"<br>");
                });
                event.preventDefault();
            });
        });
        </script>
    </body>
</html>''')

import datetime

@app.route('/', methods=['POST'])
def search_form():

    print(request.form)

    data = request.form.get('x', '')
    text = str(datetime.datetime.now()) + " | " + data

    return text

if __name__ == "__main__":
    app.run(debug=True)

Flask could also check if it is really AJAX requests and send full HTML when it is not AJAX. But to keep all lines of text it would have to remeber them somehow/somewhere - ie. in file, database or cookies.


BTW: you had few mistakes:

  • $('#searchinput') should have lower i but you have I.

  • AJAX sends data as x - see data: {x: $('#searchinput').val()}, but flask tries to get it as searchinput.

Upvotes: 1

Related Questions