Reputation: 504
What I'm trying to do and accomplishing now:
A user comes to my Django web page to submit a simple form with a couple of input fields that kicks off a complex background process in my background_process view function. I am trying to use session variables so that I can handle multiple users without variables overwriting each other during background processing. Ajax runs during the background processing calling my other view function callback_progress.
callback_progress is updating JSON with variables that are returned to my javascript/jquery ajax through return JsonResponse(data):
def callback_progress(request):
request.session["data"]['numgames'] = request.session["numgames"]
request.session["data"]['progress'] = request.session["progress"]
request.session["data"]['win_ratio'] = request.session["win_ratio"]
response = JsonResponse(request.session["data"])
return response
I can successfully return a JsonResponse from my Ajax call. Here is what my Ajax looks like and what console.log(data) looks like:
Ajax (simplified a little for readability, I'm updating some html elements in the success block that I removed)
$("#myButton").click(function result_poll() {
function ajax_call() {
$.ajax({
headers: {'X-CSRFToken': csrftoken},
type : "POST",
url : "/callback_progress/",
data: "{{ data }}",
success: function(data) {
console.log(data);
if (data["progress"] == data["numgames"] && data["progress"] != "0") {
clearInterval(interval_id);
}
},
error: function() {
console.log("something went wrong");
}
});
};
var interval_id = setInterval(ajax_call, 2000);
});
Console.log output
{numgames: "0", progress: "0", win_ratio: "0"}
{numgames: "0", progress: "0", win_ratio: "0"}
{numgames: "0", progress: "0", win_ratio: "0"}
{numgames: "0", progress: "0", win_ratio: "0"}
{numgames: "0", progress: "0", win_ratio: "0"}
Help me understand:
Why are my session variables not returned from the server with their updated values?
I can see through printing the session variable values that they are updated on my local runserver:
{numgames: "5", progress: "1", win_ratio: "0"}
{numgames: "5", progress: "2", win_ratio: "10"}
{numgames: "5", progress: "3", win_ratio: "20"}
{numgames: "5", progress: "4", win_ratio: "30"}
{numgames: "5", progress: "5", win_ratio: "40"}
Here is what I have in settings.py that is relevant from the research I have done:
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
SESSION_SAVE_EVERY_REQUEST = True
What am I missing here that allows me to return a session variable to the client with updated data while the page is loading?
I'm using Python-3.6 and Django-1.10.6
Upvotes: 2
Views: 1435
Reputation: 504
My engine problem: I was using the wrong SESSION_ENGINE for what I was trying to accomplish.
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
The signed_cookies session engine does not update the session variables for the client side to see until after an HttpResponse happens (after the page is reloaded/redirected). At least that was my experience.
I updated my session engine to using the db sessions table (which is actually the default according to the session docs):
SESSION_ENGINE = "django.contrib.sessions.backends.db"
After the engine switch: I needed to explicitly "save the existing session" to the sessions table so I looked to the save() method documented in Using Sessions Out of Views
request.session.save()
As info I still used this setting in settings.py to ensure that every request was saving my session objects:
SESSION_SAVE_EVERY_REQUEST = True
Without request.session.save()
my code did not update the session variables appropriately though.
This is my callback now that ensures the session variables are up to date for my client side ajax call:
def callback_progress(request):
request.session["data"]['numgames'] = request.session["numgames"]
request.session["data"]['progress'] = request.session["progress"]
request.session["data"]['win_ratio'] = round(request.session["win_ratio"],2)
request.session.save()
response = JsonResponse(request.session["data"])
return response
Upvotes: 3