I'm trying to output data from a celery task into a separate window. I'm a novice to JavaScript
and AJAX
, and this is where my current issue lies. After a view is executed, the celery task is initiated and the next html page (success.html
) is rendered:
success.html
{% block content %}
<body>
{% if task_id %}
<h1>task_id has been called: {{ task_id }}</h1>
<script src="{% static 'MyAPP/bootstrap/js/task_output_retrieval.js' %}"></script>
<script type='text/javascript'> task_state("{{ task_id }}"); </script>
<script src="{% static 'MyAPP/bootstrap/js/update-hello-user.js' %}"></script>
<script type='text/javascript'> second(); </script>
<h1> END </h1>
{% endif %}
</body>
{% endblock content %}
I know the JavaScript
is called, because a window is at least opened. Here is the .js
:
task_output_retrieval.js
function task_state (task_id) {
var taskID = task_id;
var newWin = window.open('', 'new window', 'width=200, height=100');
$.ajax({
url: '{% url validate_task_state %}',
data: {'taskID':taskID},
method: 'POST',
dataType : "json",
success: function(data){
$(newWin.document.body).html(data);
newWin.document.write(data);
newWin.document.close();
newWin.focus();
newWin.print();
newWin.close();
},
error: function (){ alert('An error occured'); }
});
}
task_state(task_id);
And the url.py:
url(r'^ajax/task_state/$', task_state, name='validate_task_state'), # for ajax
And the view:
admin_scripts.py
def task_state(request):
print ("You reached the task_state function")
data = 'Fail'
task_id = request.GET.get('task_id')
#task_id = request.session['task_id']
try:
async_result = AsyncResult(task_id)
except KeyError:
ret = {'error':'No optimisation (or you may have disabled cookies).'}
return HttpResponse(json.dumps(ret))
print ("request.is_ajax(): {0}".format(request.is_ajax()))
if request.is_ajax():
if 'task_id' in request.POST.keys() and request.POST['task_id']:
task_id = request.POST['task_id']
async_result.get()
data = {
'state': async_result.state,
'result': async_result.result,
}
#data = async_result.result or async_result.state
print ("data: {0}".format(data))
else:
data = 'No task_id in the request'
else:
raise SuspiciousOperation("This is not an ajax request.")
json_data = json.dumps(data)
return HttpResponse(json_data, content_type='application/json')
There are still many open issues in the task_state
I don't fully understand and through trial and error I'll get there, but right now, the task_state
is not being called. The problem I suspect is with the AJAX call (the "url") but I can't figure out why. Where am I going wrong?
Update: After checking the "JS Test Stuff" checkbox, the success.html
is rendered, error free. The AJAX JavaScript (task_output_retrieval.js
) is called from within success.html
, and this is verified because from the success.html
I'm calling 2 JavaScript files (the other being update-hello-user.js
). The window from task_output_retrieval.js
is opened and popup from update-hello-user.js
is also shown. It's within the task_output_retrieval.js where I'm calling the view:
$.ajax({
url: query_url,
)
but this is not rendered.
Here is the output from console:
[17/Aug/2018 04:59:12] INFO [django.server:124] "GET /MyApp/opt/ HTTP/1.1" 200 6631
async_result f2224e67-3e47-4980-9dc8-58622928e090
TASK_ID f2224e67-3e47-4980-9dc8-58622928e090
[17/Aug/2018 04:59:14] INFO [django.server:124] "POST /MyApp/opt/ HTTP/1.1" 200 6412
[17/Aug/2018 04:59:14] INFO [django.server:124] "GET /MyAppsite-static/MyApp/bootstrap/js/update-hello-user.js HTTP/1.1" 200 52
[17/Aug/2018 04:59:14] INFO [django.server:124] "GET /MyAppsite-static/MyApp/bootstrap/js/task_output_retrieval.js HTTP/1.1" 200 640
The issue that jumps at me looking at your code is your use of {% url validate_task_state %}
inside a JavaScript file. If you follow the most common recommended method to setup Django and serve its static content, your JavaScript files won't be processed by the template engine, and that template tag won't be processed. Also, it needs quotes around its argument so {% 'url validate_task_state' %}
You should change your success.html
template to pass the requried URL to your task_state
function, like this:
<script src="{% static 'MyAPP/bootstrap/js/task_output_retrieval.js' %}"></script>
<script type='text/javascript'> task_state("{% url 'validate_task_state' %}", "{{ task_id }}"); </script>
And modify your function to take the new argument:
function task_state (query_url, task_id) {
var taskID = task_id;
var newWin = window.open('', 'new window', 'width=200, height=100');
$.ajax({
url: query_url,
data: {'taskID':taskID},
method: 'POST',
dataType : "json",
success: function(data){
$(newWin.document.body).html(data);
newWin.document.write(data);
newWin.document.close();
newWin.focus();
newWin.print();
newWin.close();
},
error: function (){ alert('An error occured'); }
});
}
You've said in a comment that Django is not seeing the request. A common issue is CSRF protection: a custom POST request needs to pass the CSRF token, or it will be rejected. The details of how to do it depend in part on your specific configuration but generally, I do:
// Grab the CSRF token from the cookie.
var csrftoken = $.cookie('csrftoken');
$.ajax({
type: "POST",
url: "... my url ...",
headers: {
// Pass the token with the query.
'X-CSRFToken': csrftoken
},
// other ajax options...
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With