2

I am working on the new /check additional on the Finance problem. I am trying to prevent the register form from being submitted when the username is already taken, is empty, or is just one character. The /register python code is already working, so these insertions will never be allowed, just trying to prevent the form from being submitted now.

I think my jQuery code is correct, it is the following:

<script>
let input = document.querySelector('input.form-control[name="username"]');
document.querySelector('form').onsubmit = function(event) {
   $.get('/check?username=' + input.value, function(data){
         if(data === false){
            alert("This username is already taken");
            event.preventDefault();
         }
   });
}
</script>

is it located above this HTML code:

<form action="/register" method="post">
        <div class="form-group">
            <input autocomplete="off" autofocus class="form-control" name="username" placeholder="Username" type="text">
        </div>
        <div class="form-group">
            <input class="form-control" name="password" placeholder="Password" type="password">
        </div>
        <div class="form-group">
            <input class="form-control" name="confirmation" placeholder="Password" type="password">
        </div>
        <button class="btn btn-primary" type="submit">Register</button>
    </form>

However, it does not seem to be talking correctly to my python code. I was thinking maybe a problem in the JSON data I am sending back? I just can't figure it out. Would someone please help me?

@app.route("/check", methods=["GET"])
def check():
    """Return true if username available, else false, in JSON format"""
    # User reached route via POST (as by submitting a form via POST)
    if request.method == "GET":

        username = request.args.get("username")

        usernames = db.execute("SELECT username FROM users")[0][username]

        if username is not None and len(username) > 1:
            if username not in usernames:
                return jsonify(True)
            else:
                return jsonify(False)
        else:
            return jsonify(False)
2

JavaScript

$.get is asynchronous. It triggers an HTTP request and returns. The code meant to prevent submission runs after submission is processed, and therefore can't prevent it.

The preventDefault has to go into the submit handler, not the $.get callback, and would be called each time you try to submit, cancelling the submit attempt. Inside the get callback, depending on result, call the form's submit() method, that one submits the form without triggering the submit handlers again.

Python

SELECT lets db.execute return a list of dicts, so [0] would pick first record, and [username] would pick the field of the name stored in variable username. Which is not what you want, you want to compare with values. Instead of [0][username], you could do something like

usernames = (user["username"] for user in db.execute("SELECT username FROM users"))

And you can jsonify a boolean expression:

return jsonify(username in usernames)

edit: username not in usernames (according to problem description)

You might like WHERE clause in your SELECT. Gets so much more readable, saving you much code.

4
  • Thanks for your assistance! Two questions one this: I am now returning "return jsonify(username in usernames)" right after the assigning of 'usernames'. In returning this boolean, the value would be true if the username is in usernames, so I should adjust my original jQuery code to "data == true" then right? Also, how could I add my preventDefault within the $.get? I already received some help on this code piece and was adviced this was the proper way Mar 1 '19 at 11:10
  • After reading the specs, you are right, should probably be username not in usernames. Add the preventDefault in the submit callback, executed before or after $.get.
    – Blauelf
    Mar 1 '19 at 11:15
  • I'm sorry I really don't understand. If I was to put it before the $.get, would not every form submission be prevented even if the username is not in the SQL already? And how to I add it in the submit callback? Could you maybe edit it in, in the answer? Thanks again! Mar 1 '19 at 11:19
  • That's the point. When doing the call to /check, you have to decide whether to submit or not, but you don't have the data. So you cancel. And if you later discover you actually should have submitted, you do so via JavaScript.
    – Blauelf
    Mar 1 '19 at 13:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .