0

I am new to programming and wanted to make a webpage for learning purposes.

What I want to do is to display an error that says "Incorrect username/password" upon incorrect login details.

Actually I managed to do it already, however I recently learned more on making "Single Page Applications" using javascript and am trying it out. Apparently it has the advantage of not needing to load so many times.

EDIT: Upon further consideration, I realised that what I have is also sort of a "Single Page Application", my question is actually more of is it possible for Javascript to receive response from Flask without having to render a new HTML?

I want to do something that will allow me to "post" form data to flask (using javascript), and then receive either True or False depending whether login is successful or not. If its unsuccessful, i want to use .innerHTML in javascript to give an error message, otherwise I will redirect to the correct page. The purpose of this is to create a Single Page Application. prevent rendering again a new html template

Right now I managed to do it completely without javascript as below, but just want to know if there is a way to do it as I described above? Thank you for your help!

partial flasktest.py # /check_login does the authentication. /login will render the frontpage and pass the "invalid" parameter.

@app.route('/login')
def login_page():
    return render_template('frontpage_login.html', invalid = bool(request.args.get('invalid')))

@app.route('/check_login', methods = ['POST'])
def check_login():
    if request.method == 'POST':
        password = request.form['Password']
        username = request.form['Username']
        tempuser = User.query.filter_by(username = username).first()
        if tempuser is not None:
            if hashpass(password) == tempuser.password:

                login_user(tempuser)

                flash("Logged in successfully.")
                
                return redirect(url_for('home_page'))
       
    return redirect(url_for('login_page', invalid = True))

frontpage_login.html # basically a normal login page, will render the message if invalid == true.

{% extends 'frontpage_template.html' %}

{% block head %}
<a href="{{ url_for('front_page')}}">Home</a>
<div class = "currentlink"><a href="{{ url_for('login_page') }}">Login</a></div>
<a href="{{ url_for('register_page') }}">Register</a>
{% endblock %}



{% block content %}

<div class = "loginform">
<form action = "{{ url_for('check_login') }}" method = "POST">
    <label for="Username" autofocus>Username</label><br>
    <input type="text" id = "Username" name = "Username"><br>
    <label for="Password">Password</label><br>
    <input type="password" id = "Password" name = "Password"><br>
    <input id = "Login" type = "submit" value = "Login">
</form>
</div>

{% if invalid == True %}
<p class = 'error'>The username or password is invalid!</p>
{% endif %}


{% endblock %}
hkcode
  • 309
  • 1
  • 8
  • Does this answer your question? [How can I pass data from Flask to JavaScript in a template?](https://stackoverflow.com/questions/11178426/how-can-i-pass-data-from-flask-to-javascript-in-a-template) – Liam Jun 24 '20 at 14:35
  • @Liam not really, I am asking how to pass variables from flask to javascript without having to render a new page – hkcode Jun 24 '20 at 14:37

1 Answers1

1

On the server side you would need to return some kind of data instead of a redirect if the password/username is invalid.

On the Client Side with JavaScript you could post the HTML form as an AJAX call and display the message on the callback.

Anyways I would recommend you to use jQuery for this since its functionality simplifies this quite much. With jQuery a basic AJAX call looks like this:

$('input#loginButton').click( function() {
    $.ajax({
        url: 'flask-url',
        type: 'post',
        dataType: 'json',
        data: $('form#loginForm').serialize(),
        success: function(data) {
             // display user dialog 
             $('#errorDialog').text('Incorrect username/password');
        }
    });
 });

If you want to do this with pure JavaScript you can do something like this:

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
  if (this.readyState == 4 && this.status == 200) {
     // do innerHTML changes
     document.getElementById('errorDialog').innerHTML = "Incorrect username/password";
  }
};
xhttp.open('POST', 'flask-url', true);
xhttp.send();

Where onreadystatechanged means that you got some kind of response by the server

Edit: Since you asked when to use Websockets or AJAX Calls this link should help you.

If you want to implement Websockets with Flask I would recommend you to use flask-socketio which you can simply install via pip.

Feel free to ask if something is still unclear.

Daniel
  • 398
  • 2
  • 16
  • is it preferred to use something like socket.io as the other person mentioned instead of pure javascript? also, I haven't learn jquery yet, but from what I interpret from your code, is that "success" is basically if a response is received right? Do I have to care what type of response to give to be considered success? – hkcode Jun 24 '20 at 18:03
  • Firstly you cannot compare socket.io to javascript since socket.io is a library for javascript whereas JavaScript is the programming language. Socket.io is needed for real-time applications where you need Websockets which is especially good if you have to send much data repeatedly, and want to get rid of the overhead of repeated GET/POST Requests, which is unnecessary in your case. – Daniel Jun 24 '20 at 18:26
  • Yes, success is what is asynchronously executed if the Server responds with Status OK which is Code 200. The type is irrelevant except if you want to return a Status Code manually. In your case you yould simply return any variable or JSON etc. – Daniel Jun 24 '20 at 18:29