1

I am using jquery elements that a user can drag and drop. I post the order of the elements to django using ajax.

Inside the django view I am able to work with the data that is posted from ajax.

Django views:

#this is the view where the jquery elements are being ordered by the user
def inside_exam(request):


    if request.method=='POST':
        form = MyForm(request.POST)
        if form.is_valid():
           #here I am able to retrieve the data from ajax and save it to a django model, code not shown here

           return redirect('exam_results')


#the view redirected to from the inside_exam view
def exam_results(request):

    #here I set the score for the exam and set the context, code not shown here 

    print(“all is set”)
    return render(request, 'quizresults.html', context)

The print(“all is set”) is executed and I am able to print the html for quizresults.html in the browser. No errors are in the terminal window and this is shown in the terminal: "GET /exam_results/ HTTP/1.1" 200 8981.

But the same template is still shown, it is not showing the quizresults.html template. Any idea why the render(request, 'quizresults.html', context) is not working as expected?

By the way: when I use a django form without the jquery, everything works fine and the quizresults.html template is shown.

Since I want to show the user another template, but not update the current template, is ajax maybe not the correct way to send the jquery data in this case? If not, what would be a better way?

Edit, ajax code:

function dataToSend() {
    {% load static %}
     var node2 = document.getElementById('sortable');
     var idsInOrder = $("#sortable").sortable('toArray');
     console.log("the ids");
     console.log(idsInOrder);

     var fd = new FormData();
     for(var i=0; i<idsInOrder.length; i++) {
          j = i+1
          fd.append('a'+j, idsInOrder[i]);
     }

     $.ajax({
       type: 'POST',
       data: fd,
       cache: false,
       processData: false,
       contentType: false
     }).done(function(data) {
       //The data from the quizresults.html template is printed out here, but that template is not shown, the template in the browser is still the insidequiz.html template.
       console.log("the data");
       console.log(data);
     });
 }


 window.onload = function init() {
     function getCookie(name) {
       var cookieValue = null;
       if (document.cookie && document.cookie !== '') {
         var cookies = document.cookie.split(';');
         for (var i = 0; i < cookies.length; i++) {
           var cookie = jQuery.trim(cookies[i]);
           if (cookie.substring(0, name.length + 1) === (name + '=')) {
             cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
             break;
           }
         }
       }
       return cookieValue;
     }

     var csrftoken = getCookie('csrftoken');

     function csrfSafeMethod(method) {
         return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
     }
     $.ajaxSetup({
         beforeSend: function(xhr, settings) {
             if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
             }
         }
     });
};
5
  • Please post the AJAX code. Commented Aug 24, 2017 at 19:03
  • I have now added the ajax code. Commented Aug 24, 2017 at 19:21
  • are logs showing in the console ? Commented Aug 24, 2017 at 19:25
  • Yes they are, the problem has to do with the redirect. Probably ajax is the reason for the page to stay in the same template instead of redirecting to the other template. Commented Aug 24, 2017 at 19:28
  • Yes, you can actually make exam_results method as a helper method to do more work, as required and then send the rendered template through inside_exam method only. Because redirect will send a HttpResponseRedirect object with the wrong status code. Commented Aug 24, 2017 at 19:32

2 Answers 2

1

Using redirect shortcut method in Django will return a HttpResponseRedirect object back to the AJAX, which it will be processed as a 302 Found status code, which then will make another request to the redirected resource and get the content. This does not seem to be the right way to do it, even though you get the content.

You can use the method exam_results to do the other work and return the required context, which shall be used to return the HttpResponse object using render method.
Then, with the data you get, you can replace the document with the template you receive.

Solution:

# views

#this is the view where the jquery elements are being ordered by the user
def inside_exam(request):
    if request.method=='POST':
        form = MyForm(request.POST)
        if form.is_valid():
           #here I am able to retrieve the data from ajax and save it to a django model, code not shown here

           context = exam_results(request)

           return render(request, 'quizresults.html', context)


# method to set the score for the exam
# return context from this method
def exam_results(request):

    #here I set the score for the exam and set the context, code not shown here 

    # build context
    return context


 # javascript

     $.ajax({
       type: 'POST',
       data: fd,
       cache: false,
       processData: false,
       contentType: false
     }).done(function(data) {
       //The data from the quizresults.html template is printed out here, but that template is not shown, the template in the browser is still the insidequiz.html template.
       console.log("the data");
       console.log(data);

       // replace the page with the new template
       var newDoc = document.open("text/html", "replace");
       newDoc.write(data);
       newDoc.close();

       // update the url
       window.history.pushState('', 'title', "newurl");
     });

Ref: History API MDN

Sign up to request clarification or add additional context in comments.

4 Comments

This works, but gives warning in the console: A Parser-blocking, cross site (i.e. different eTLD+1) script, code.jquery.com/jquery-1.12.4.js, is invoked via document.write. The network request for this script MAY be blocked by the browser in this or a future page load due to poor network connectivity. If blocked in this page load, it will be confirmed in a subsequent console message.See chromestatus.com/feature/5718547946799104 for more details.
A much better way would be to send only the part of the HTML that seems to be changing in the whole HTML. Modify your template quizresults.html that way and then, $('#elementToBeReplacedId').html(data) where data is the success callback receives as response.`
Thanks for your help. The url doesn´t change in the browser (because newDoc.write(data) is not really a redirect). So I ended up using an HTML form and using Javascript I added data and submitted the form to a url.
You can change the url in browser as well. I edited the ajax success method.
0

I figured that ajax makes things complicated when it comes to redirecting. What I ended up doing was to create an HTML form (that is hidden) and then post that form to a url using javascript. No need for ajax.

HTML code:

 <form id="form1" action='{% url 'inside_exam' %}' method="post" style="display:none;">
   {% csrf_token %}
 </form>

 <p> <button type='submit' style="visibility" class="button button-long button-primary" onclick="sendData(this);">Send</button></p>

javascript code:

function sendData() {
  var idsInOrder = $("#sortable").sortable('toArray');
  var form = document.getElementById('form1');    
  for(var i=0; i<idsInOrder.length; i++) {
      j = i+1
      var hiddenField = document.createElement("input");
      hiddenField.setAttribute("type", "hidden");
      hiddenField.setAttribute("name", 'a'+j);
      hiddenField.setAttribute("value", idsInOrder[i]);

      form.appendChild(hiddenField);
  }
  console.log("form is:");
  console.log(form);

  form.submit();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.