问题
I am trying to make a web application based on Django that takes user input and performs Heavy background task that completes in almost five to ten minutes. When the background task is completed, few parameters are supplied to the template to render. Everything works fine and the page loads after that.
But when I am trying to use AJAX for this as it does'nt seems good that the page is loading for so long due to background heavy processing, I am not able to figure out how to reload the page (Though I am able to show an alert on completion but instead of this I want to re-render the page)
Here is my views.py code:
def index(request):
#All Background process code goes here
return render(request, 'form.html', {'scanResults' : scanResults, 'context_list' : context_list, 'scanSummary' : scanSummary})
Here is my AJAX call
$(document).on('submit','#scanForm', function(e){
e.preventDefault();
$.ajax({
type: 'POST',
url: '/scanner/',
data: {
email: $('#email').val(),
context: $('#context').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
},
success:function(response){
alert('Scan Completed');
location.reload();
}
});
});
I am not able to figure out, what should I write in success function to reload the page that index function has returned to template.
My main motive is to show a progress bar that tells the progress of process in background (I have'nt implemented the code yet )and once the process is completed , refresh the page with response.
Thank You
回答1:
If you want to check the progress of a process you may need a polling mechanism
as a solution.
This requires you to have a Model that has a state to determine if your scan
is still in progress or has succeeded.
Since you will reload the page to display the results, you should have
a logic in your index view to return a different template or context
for when a user has yet to start scanning and when the scanning is successful.
from django.http import JsonResponse
def index(request):
if status == 'success':
# `status` may come from a Model which has a state .
# If `status` is 'success' this means that your scanning has
# finished so you can have a different page or update context_list
# based on success data.
# Display input form
form = scannerForm()
return render(request, 'form.html', {
'form': form,
'context_list' : context_list,
'scanSummary' : scanSummary
})
You need a view to continuously check the scan status and returns a JSON response.
def scanner(request):
#All Background process code goes here
form = scannerForm(request.POST)
status = form.perform_task()
# During the task, your Model state should also be
# updated and return the status whether it is success, pending or failed etc..
return JsonResponse({
'status': status,
})
Run the ajax poll to check the scanner view.
$(document).on('submit','#scanForm', function(e){
e.preventDefault();
checkScanStatus();
});
function checkScanStatus () {
$.ajax({
type: 'POST',
url: '/scanner/',
data: {
email: $('#email').val(),
context: $('#context').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
},
success: handleCheckScanStatus,
error: handleScanError
});
}
function handleCheckScanStatus (result) {
if (result.status == 'success') {
// Reload the page and display the condition you set for 'success' state
// on the `index` view.
location.reload();
} else {
// Show progress bar indicating that the process running in the background
const interval = 5000; // Five seconds
window.setTimeout(checkScanStatus, interval);
}
}
function handleScanError (response) {
console.error(response)
}
I would suggest to look into django celery for async tasks and django-fsm for transitioning model states.
If you just want a simple loader and do not need the check the specific status of your background task, you can use jQuery AJAX's beforeSend method to display a progress bar until the AJAX request finishes.
来源:https://stackoverflow.com/questions/50961625/django-render-template-on-ajax-success