The problem I face has to do with re-rendering a Django view based on a context that is updated by an AJAX post request that is initiated by jQuery. The reason why I need an AJAX request is because I need to modify the page UI without refreshing the page, which is critical to what I want to build.
So far, I am able to trigger the AJAX post request to the URL of the same page where the update is supposed to occur, and the Django view.py
adequately registers that it has been called. However, although I can reproduce the ability to update the Django view's context, the view does not seem to re-render an updated HTML based on the updated context.
The thread at How to re-render django template code on AJAX call seems to describe exactly my problem. The top-voted solution of this thread is to have a conditional that is only triggered in case of an AJAX call that renders only a partial template (not the full HTML page) - a partial template that corresponds to the component to be updated. This is what's being reproduced in the code snippets below, but the HTML does not change based on the updated context.
Attached are the relevant code snippets for a simple attempt where the page displays <h1>2<h1/>
by default and is meant to be updated to 5 when we click anywhere on the window. Clicking anywhere on the window triggers the AJAX call, but the page is not updated with <h1>5<h1/>
.
view.py
def index(request):
context = {"num": 2}
if (request.method == "POST"):
print("View hit due to AJAX call!") # // THIS CAN BE TRIGGERED ADEQUATELY!
context["num"] = 5
return render(request, 'num.html', context)
return render(request, 'override.html', context)
override.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="{% static 'js/num.js' %}" defer></script>
<title>Title</title>
</head>
<body class="">
<div class="">
{% include 'num.html' %}
</div>
</body>
</html>
num.html
<h1>{{ num }}</h1>
num.js
var postUrl = "http://localhost:8000/";
function getCSRFToken() {
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, 10) == ('csrftoken' + '=')) {
cookieValue = decodeURIComponent(cookie.substring(10));
break;
}
}
}
return cookieValue;
}
$('html').click(function(){
values = [1, 2];
var jsonText = JSON.stringify(values);
$.ajax({
url: postUrl,
headers: { "X-CSRFToken": getCSRFToken(), "X-Requested-With": "XMLHttpRequest" },
type: 'POST',
data: jsonText, // note the data, jsonText, does not really matter. The Django context gets updated to 5 instead of 2.
traditional: true,
dataType: 'html',
success: function(result){
console.log("AJAX successful") // THIS CAN BE TRIGGERED ADEQUATELY!
}
});
});