sktrinh12 / chemITryFlask

chemoinformatics webapp used to investigate chemical compound dataset scraped online; use of various visualization libraries
0 stars 0 forks source link

Login issues #1

Open nqtran opened 5 years ago

nqtran commented 5 years ago

I think I see the problem with your login. You are locking the form correctly but you do not make a request back to your back end. The following block is redundant.

    // re-enable the form
     $(document).ready(function() { 
       $('#form-subsrch').submit(function(){
         lockModal.css("display", "none");
         loadingCircle.css("display", "none");

       form.children("input").each(function() {
         $(this).attr("readonly", false);
        }); 
     });

You have already defined the submit event for you form on line 34. What you want to do instead is send a POST request to your backend. You have several ways of doing this with jQuery. First the via jQuery.ajax.

    $.ajax({
        url: '/login',
        data: form.serialize(),
        type: 'POST',
        success: function(response) {
            \\ unlock your form
        },
        error: function(error) {
            \\ show error message
        }
    });

This block will send a POST request to your /login route. Notice that the ajax method takes a JavaScript Object. The url and type fields are self explanatory. The data field is the body (sometimes called payload) of your request. The serialize() method turns your jQuery form object in to a JSON. The success and error fields take a method as a value. These methods are executed when the POST request succeeds or fails based on the HTML response code (this logic flow is called a callback) respectively. In the error method you would show your error message. In the success method you would unlock your form. This however is redundant as your flask code redirects to a different page on a successful log in. https://codehandbook.org/python-flask-jquery-ajax-post/

Your second option is using jQuery's post method. It's just a shorthand method of doing an AJAX call like the one above.

    $.post('login', form.serialize(), function(response){
        // unlock your form
    })
    .fail(function() {
        // show error message
    });

https://api.jquery.com/jquery.post/

Your final option is a little messier. You can rely on HTML5 form tag's attributes. You currently have in your login.html <form action="" class="form-inline" method="post">. The HTML DOM has its own JavaScript logic to handle forms. When you define the method attribute of a form tag as post, you are telling DOM to do a POST request when the user submits the form. In this case, clicking the button with the attribute type="submit" it will POST with a JSON representation of the form as the payload. What you are missing is the a value for the action attribute, which should be pointing to the route of your login. So as a third option you can get rid the original JavaScript block and change form tag to the following.

<form action="/login" class="form-inline" method="post">

This will now send a POST request when you submit the form.

This however this has a few drawbacks. There is no elegant way of showing an error message if the user fails to login being the biggest one.
https://www.w3schools.com/tags/att_form_method.asp

nqtran commented 5 years ago

There might also be a way to do this using flacks's request context. However I'm not familiar with how flask, jinja, and jQuery interact.

sktrinh12 commented 5 years ago

Hey Nguyen, I'm getting this error when using ajax method:

flask.debughelpers.FormDataRoutingRedirect: b'A request was sent to this URL (http://127.0.0.1:5000/smrtsrch) but a redirect was issued automatically by the routing system to "http://127.0.0.1:5000/smrtsrch/". The URL was defined with a trailing slash so Flask will automatically redirect to the URL with the trailing slash if it was accessed without one. Make sure to directly send your POST-request to this URL since we can\'t make browsers or HTTP clients redirect with form data reliably or without user interaction.\n\nNote: this exception is only raised in debug mode'

I removed the redundant block and replaced with:

$.ajax({ url: '/smrtsrch', data: $('form-subsrch').serialize(), type: 'POST', success: function(response) { lockModal.css("display","none"); loadingCircle.css("display","none"); }, error: function(error) { console.log(error); } }); }); });

I guess my question is, what javascript object do I need to feed it? Does this mean I have to convert my data into a javascript object? Thanks for your help.

nqtran commented 5 years ago

The url you should be using is definitely /login or /login/. This is defined in your python code. As for your question, The JavaScript object you should be Using is the object representing the html tag

. You access this using a css selector in the $() command. Your current selector now would fail as it is trying to find a tag, which doesn’t exist. I would instead add a Id or name to your tag and use the corresponding selector. https://www.w3schools.com/jquery/jquery_ref_selectors.asp

As for your other question, it depends on what you mean by data. If you are referring to your username and password then that should already be a part of your form object. If you want to define your own JS object then instead send {username: $(‘input[name=“username”]’).val(), password: $(‘input[name=“password”]’).val()}. All I am doing here is creating a new JS object with the username and password key value pairs. Notice how I’m using css selectors to find the correct tag.

sktrinh12 commented 5 years ago

oh, but the form is not for logging in thru the /login route. It is a 'search engine' for lack of vocab. It will search a database for matches. I named the route, /smrtsrch. So that is why I thought to put the URL as that. I named the form class = 'form-subsrch'. Do i need the '.' in front? class='.form-subsrch'. BTW, the flask route will return a list.

nqtran commented 5 years ago

Ahh I see, I was confused. I thought this was for your login page. If you are search for a class you will use ., but using the id would be better #form-subsrch (you may end up using a class again but you can't reuse an id).

nqtran commented 5 years ago

Based on your flask code the data should be injected as svgoutput into your template via Jinja.