I tried to break this problem down into the simplest example. When the request is ajax, rendering the page with an updated context doesn't produce the expected result.
index.html:
<html>
<body>
{% if templateVariable %}
<h1>{{ templateVariable }}</h1>
{% endif %}
<button id="testBtn">TEST</button>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$(function() {
$('#testBtn').click(function(event) {
$.ajax({
type: "POST",
url: "./",
data: {
'x' : 'x',
'csrfmiddlewaretoken' : '{{ csrf_token }}'
}
});
});
});
});
</script>
</body>
</html>
views.py
def index(request):
context = {}
if 'x' in request.POST:
context['templateVariable'] = 'I was updated via ajax'
print('ajax ran')
return render(request, 'index.html', context)
context['templateVariable'] = 'I was not updated via ajax'
print('ajax was not run')
return render(request, 'index.html', context)
When I first load the page, 'ajax was not run' is printed, templateVariable is 'I was not updated via ajax', and the page renders with that in the h1 tag as expected.
When I click the testBtn, I expect the ajax request to trigger the if statement, update the context, and render the page with 'I was updated by ajax' in the h1 tag.
Instead, 'ajax ran' is printed but templateVariable remains 'I was not updated by ajax' when the page is rendered. 'ajax was not run' only is printed once when the page is loaded initially.
Why would I not be getting the expected result?
EDIT: It seems everyone agrees that you cannot return a render and update context variables with an ajax request but I'm still having trouble with this as I believe this is possible. Here's some alternate code:
index2.html:
<html>
<body>
{% if templateVariable %}
<h1>{{ templateVariable }}</h1>
{% endif %}
<h1 id="placeHolder"></h1>
<button id="testBtn">TEST</button>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$(function() {
$('#testBtn').click(function(event) {
$.ajax({
type: "POST",
url: "./",
data: {
'x' : 'x',
'csrfmiddlewaretoken' : '{{ csrf_token }}'
},
success: function (data) {
$('#placeHolder').html(data);
},
dataType: 'html'
});
});
});
});
</script>
</body>
</html>
views2.py
def index2(request):
context = {}
if 'x' in request.POST:
context['templateVariable'] = 'I was updated via ajax'
print('ajax ran')
return render_to_response('notIndex.html', context)
context['templateVariable'] = 'I was not updated via ajax'
print('ajax was not run')
return render(request, 'index.html', context)
notIndex.html:
{% if templateVariable %}
{{ templateVariable }}
{% endif %}
- In this example, the page is initially loaded with templateVariable in the context as 'I was not updated via ajax'.
- When testBtn is clicked, the ajax request triggers the if block in the view. This renders notIndex.html with the updated context.
- The success function of the ajax call sets the generated html from notIndex.html to the h1 tag.
So why is it only possible to trigger a page render with ajax if the page is not the same one that the ajax call came from?