1

What's happening now is when I click submit ("Go!"), Django clears the entire page and then prints the correct JSON response results_matrix on a blank page. alert("success") does not appear or alert("error"). I don't know why the post function is doing this since I'm not returning a render of anything.

Before clicking "Go!":

enter image description here

After clicking "Go!" in Chrome:

enter image description here

After clicking "Go!" in Internet Explorer: enter image description here

The ajax call is returning a raw json file to download (which Chrome displays automatically in the browser) instead of going into the ajax success function.

Expected Behavior: Page remains the same while a pop-up appears saying, "success".

In index.js:

$(document).ready(function() {
        
  var csrftoken = Cookies.get("csrftoken");

  function csrfSafeMethod(method) {
      // these HTTP methods do not require CSRF protection
      return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  }

  $.ajaxSetup({
      beforeSend: function (xhr, settings) {
          if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
              xhr.setRequestHeader("X-CSRFToken", csrftoken);
          }
      }
  });  

  $(document).on("submit","#weather_form",function(event){
    // //Prevent default django post behaviour for a form submission.
    event.preventDefault();

    $.ajax({
      url: "/weather/",
      type: "POST",
      data: {type_of_person: $("#id_type_of_person").val(),
        exercise: $("#id_exercise").val(),
        unit: $("#id_unit").val(),
        zip_postal: $("#id_zip_postal").val()},
      dataType: "json",
      contentType: "application/json",
      success: function (data){
        alert("success");
      },
      error: function(xhr,errmsg,err) {
        alert("error");
        console.log(errmsg + "\n" + xhr.status + ": " + xhr.responseText)
      }
    });

    return false;
  });
});

In index.html:

           <form action="/weather/" method="post" autocomplete="off" id="weather_form">
                {% csrf_token %}
                {{ form.non_field_errors }}
                {{ error }}
                <ul>
                    <li class="center_text">
                        <h3>Best Time to Go Out</h3>
                    </li>
                    <li>
                        <label>{{ form.type_of_person.label }}: </label>
                        {{ form.type_of_person }}
                        {{ form.type_of_person.errors }}
                    </li>
                    <li>
                        <label>{{ form.exercise.label }}: </label>
                        {{ form.exercise }}
                        {{ form.exercise.errors }}
                    </li>
                    <li>
                        <label>{{ form.unit.label }}: </label>
                        {{ form.unit }}
                        {{ form.unit.errors }}
                    </li>
                    <li>
                        <label>{{ form.zip_postal.label }}: </label>
                        {{ form.zip_postal }}
                        {{ form.zip_postal.errors }}
                    </li>
                    <li>
                        <input id="go" type="submit" value="Go!">
                    </li>
                </ul>
            </form>

In views.py:

class weather(base.TemplateView):
    ...

    @staticmethod
    def post(request, *args, **kwargs):
        ...
        if form.is_valid():
            ...
            return http.JsonResponse({"results_matrix": results_matrix.tolist()}, status=200)
        else:
            return http.JsonResponse({"error": form.errors}, status=400)

Edit #1:

The request made after clicking "Go!": enter image description here

Details: enter image description here

enter image description here

Edit #2:

Other things I tried, but to no avail:

  • Adding async: false to the ajax call.
  • Directing the ajax call to be handled by another view rather than the current view.

Edit #3:

Dependencies for this web app:

  • jquery-ui-1.12.1/jquery-ui.min.css

  • jquery-ui-1.12.1/jquery-ui.structure.min.css

  • jquery-ui-1.12.1/jquery-ui.theme.min.css

  • jquery-3.5.1.min.js

  • jquery-ui-1.12.1/jquery-ui.min.js

  • index.js

  • index.css

  • Django 3.1

NoName
  • 9,824
  • 5
  • 32
  • 52
  • I think you should use the data you pass to success function somehow. For example you can try to load it to div like: `$('.class').html(data);` – bkrop Sep 23 '20 at 18:48
  • your form is still getting submit .Can you try like [this](https://stackoverflow.com/a/6462306/10606400) ? – Swati Sep 24 '20 at 03:58
  • @Swati Same problem. – NoName Sep 24 '20 at 04:04
  • Is there `action=".."` under your form tag ? Also is there ``? – Swati Sep 24 '20 at 04:35
  • 1
    try adding `return false` on the end of the function, so the form/page isnt actually submitted, only the ajax will be executed. – yedpodtrzitko Sep 24 '20 at 04:58
  • @Swati I've updated my question with the form html – NoName Sep 24 '20 at 05:01
  • @yedpodtrzitko Same thing happens, so I guess that's not the problem and event.preventDefault(); is working properly. – NoName Sep 24 '20 at 05:02
  • @NoName isnt there any JS error in browser's console which could cause JS being ignored? Can you add `print(request.is_ajax)` into the view to see if the request is dispatched by ajax or a regular request? – yedpodtrzitko Sep 24 '20 at 05:28
  • @yedpodtrzitko `print(request.is_ajax)` gives `>`, so the request is in fact ajax. – NoName Sep 24 '20 at 05:45
  • my bad, do `.is_ajax()`... the method is always defined, it does not mean the request is ajax. – yedpodtrzitko Sep 24 '20 at 05:49
  • I have limited knowledge in django.. but as you see your form action is also going to same page where you are sending your ajax .. remove that `action=".."` and see onces .. – Swati Sep 24 '20 at 12:44
  • @yedpodtrzitko I have removed the deprecated `.is_ajax`, and I've updated the code. `request.is_ajax()` was returning false, but I was incorrectly using `request.is_ajax`, and it was going through every time. Now, `request.method ` in fact retunrs `POST`, but I'm still getting the same results. – NoName Sep 24 '20 at 21:52
  • @Swati Removing `action="..."` gives the same results. It didn't matter because we are preventing its default form submission behavior with `event.preventDefault();` – NoName Sep 24 '20 at 21:55
  • @NoName if `request.is_ajax()` is returning `False`, that means you're not doing ajax request, but the form is submitted normally without triggering the `submit` handler. So that confirms what is the actual problem. Now the reason why is because you shouldnt use form submit handler this way, but as follows: https://stackoverflow.com/questions/18545941/jquery-on-submit-event – yedpodtrzitko Sep 25 '20 at 01:05
  • Does this answer your question? [Jquery .on() submit event](https://stackoverflow.com/questions/18545941/jquery-on-submit-event) – yedpodtrzitko Sep 25 '20 at 01:05
  • @yedpodtrzitko I tried it, same problem. We know ajax is running because the returned `results_matrix` is correct with respect to the data passed by ajax. But it is replacing the entire page and not running the success function. – NoName Sep 25 '20 at 16:58
  • @NoName `request.is_ajax()` returning `False` together with the blank page and no `alert()` makes me not convinced it's ajax. If you observe requests in "Network" tab in browser's Developer Tools, is it really marked there as XHR request? Also you didnt answer the question if there's any JS error in browser's console. – yedpodtrzitko Sep 25 '20 at 17:07
  • @yedpodtrzitko Oh you're right! See my edit. I think we're close to cracking this one! Still not sure what the errors means. If the POST request is aborted, why is it returning the correct response? – NoName Sep 25 '20 at 17:47
  • please post the latest version of your javascript.This one wont work as explained in another question linked above, so we know what is your current code. – yedpodtrzitko Sep 25 '20 at 18:23
  • @yedpodtrzitko Done! The result is the same though. – NoName Sep 25 '20 at 18:40
  • 1
    Try updating `$(document).on("submit","#weather_form",function(){ ` to accept the scoped `event` parameter eg `$(document).on("submit","#weather_form",function(event){ ` followed by 'event.preventDefault();` while simultaneously ending the function with `return false;` after the ajax call. – ggordon Sep 25 '20 at 19:44
  • @ggordon Done, I'm updated the `index.js` in the question but the exact same problem occurs. – NoName Sep 26 '20 at 04:47
  • The error is gone after adding `dataType: "json", contentType: "application/json",` to the ajax parameters, but the main problem persists. Why is the ajax response giving me a json file to download and open directly in the browser (hence the blank page with a line of string) instead of going in the success function? – NoName Sep 26 '20 at 05:32
  • Can you remove screenshots which are outdated? It's difficult to tell which ones are outdated. If none of them is up-to-date, can you add info about the request which is going through now? Ideally just as a text, not as a screenshot. Also why is your view's `post` decorated with `@staticmethod`, I've never seen that. Why do you have `if request.method == "POST":` in your `post()` method when `post()` is always dispatched via `POST` method? – yedpodtrzitko Sep 26 '20 at 06:57
  • @yedpodtrzitko All of them are up-to-date. `@staticmethod` because it can function without any reference argument whether it is called by an instance of a class or by the class itself. Mainly used to improve code readability, signifying that the method does not depend on state of the object itself. But you're right about the if-statement, I'll remove it. – NoName Sep 27 '20 at 08:49

2 Answers2

0

just remove weather URL from action attribute. because it's call weather class before calling ajax.

       <form action="" method="post" autocomplete="off" id="weather_form">
            {% csrf_token %}
            {{ form.non_field_errors }}
            {{ error }}
            <ul>
                <li class="center_text">
                    <h3>Best Time to Go Out</h3>
                </li>
                <li>
                    <label>{{ form.type_of_person.label }}: </label>
                    {{ form.type_of_person }}
                    {{ form.type_of_person.errors }}
                </li>
                <li>
                    <label>{{ form.exercise.label }}: </label>
                    {{ form.exercise }}
                    {{ form.exercise.errors }}
                </li>
                <li>
                    <label>{{ form.unit.label }}: </label>
                    {{ form.unit }}
                    {{ form.unit.errors }}
                </li>
                <li>
                    <label>{{ form.zip_postal.label }}: </label>
                    {{ form.zip_postal }}
                    {{ form.zip_postal.errors }}
                </li>
                <li>
                    <input id="go" type="submit" value="Go!">
                </li>
            </ul>
        </form>
Umair Lakhani
  • 211
  • 1
  • 8
0

Finally found the root of the problem. Jesus christ.

In my index.js, I have:

var csrftoken = Cookies.get("csrftoken");

but I never imported the JavaScript Cookie library.

I ended up not using the library and solved this by replacing the above line with the following:

function getCookie(name) {
      let cookieValue = null;
      if (document.cookie && document.cookie !== '') {
          const cookies = document.cookie.split(';');
          for (let i = 0; i < cookies.length; i++) {
              const cookie = cookies[i].trim();
              // Does this cookie string begin with the name we want?
              if (cookie.substring(0, name.length + 1) === (name + '=')) {
                  cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                  break;
              }
          }
      }
      return cookieValue;
}

var csrftoken = getCookie('csrftoken');
NoName
  • 9,824
  • 5
  • 32
  • 52