I’m working on a Django project where I need to handle a task that runs in the background. Once the task is completed, I want to reload the current page, but I also need it to load a specific HTML template on that same URL.
Currently, I’m using AJAX to poll the status of the task, and once it’s completed, I receive a JSON response from the server indicating the task’s completion. My goal is to reload the current page when the task is done, so the user can see the updated content.
I want that if the user visits the page later or deletes or reloads the tab the new template is what is loaded and not the old one.
Here’s my django view:
@csrf_protect
def initiate_transcription(request, session_id):
file_name = request.session.get('uploaded_file_name')
file_path = request.session.get('uploaded_file_path')
try:
transcribed_doc = TranscribedDocument.objects.get(id=session_id)
except TranscribedDocument.DoesNotExist:
return JsonResponse({'status': 'error', 'message': 'Document not found'}, status=404)
if request.method == 'GET':
if not file_name or not file_path:
return redirect(reverse('transcribeSubmit'))
if request.method == 'POST':
if not file_name or not file_path:
return redirect(reverse('transcribeSubmit'))
else:
try:
if transcribed_doc.state == 'not_started':
transcribed_doc.state = 'in_progress'
transcribed_doc.save()
audio_language = request.POST.get('audio_language')
output_file_type = request.POST.get('output_file_type')
task = transcribe_file_task.delay(file_path, audio_language, output_file_type, 'ai_transcribe_output', session_id)
return JsonResponse({'status': 'success', 'task_id': task.id})
elif transcribed_doc.state == 'completed':
return render(request, 'transcribe/transcript-download.html')
except Exception as e:
#return HttpResponse(status=500)
return JsonResponse({'status': 'error', 'error': 'No file uploaded'})
return render(request, 'transcribe/transcribe-complete-en.html')
@csrf_protect
def poll_task_status(request, task_id):
import base64
task_result = AsyncResult(task_id)
if task_result.ready():
session_id = request.session.get('session_id')
try:
transcribed_doc = TranscribedDocument.objects.get(id=session_id)
if transcribed_doc.output_file:
transcribed_doc.state = 'completed'
transcript_path = transcribed_doc.output_file.url
transcript_name = os.path.basename(transcript_path)
transcript_path_response = requests.get(transcript_path)
if transcript_path_response.status_code == 200:
file_content = transcript_path_response.content
file_content_base64 = base64.b64encode(file_content).decode('utf-8')
response_data = {
'status': 'completed',
'file_content': file_content_base64,
'content_type': 'text/plain; charset=utf-8',
'filename': transcript_name
}
return JsonResponse(response_data)
#return render(request, 'transcribe/transcript-download.html')
#context = {
#'download_url': transcribed_doc.output_file.url,
#'filename': transcribed_doc.output_file.name,
#}
else:
return JsonResponse({'status': 'error', 'message': 'Failed to retrieve file'}, status=500)
else:
return JsonResponse({'status': 'terminated', 'message': 'Transcription was terminated before completion'})
except TranscribedDocument.DoesNotExist:
return JsonResponse({'status': 'error', 'message': 'Transcription document not found'}, status=404)
elif task_result.state == 'REVOKED':
transcribed_doc.state = 'terminated'
transcribed_doc.save()
return JsonResponse({'status': 'terminated', 'message': 'Transcription was terminated'})
else:
return JsonResponse({'status': 'pending'})
Here is my JS:
form.addEventListener('submit', function(event) {
event.preventDefault();
isTranscribing = true;
const transcribeField = document.querySelector('.transcribe-output-lang-select')
transcribeField.style.opacity = '0';
setTimeout(function() {
transcribeField.style.display = 'none';
transcribingFileField.style.display = 'block';
errorDiv.style.opacity = '0';
errorDiv.style.display = 'none';
}, 300);
setTimeout(function() {
transcribingFileField.style.opacity = '1'
}, 500);
const formData = new FormData(form);
const xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.status == 200) {
const response = JSON.parse(xhr.responseText);
if (response.status === 'success') {
pollTaskStatus(response.task_id);
} else {
showError('An error occurred while initiating the transcription.');
}
} else {
showError('An error occurred while uploading the file.');
}
};
xhr.onerror = function() {
showError('An error occurred while uploading the file.');
};
xhr.open('POST', form.action, true);
xhr.send(formData);
});
function pollTaskStatus(taskId) {
currentTaskId = taskId;
console.log(currentTaskId)
pollInterval = setInterval(() => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.status == 200) {
const response = JSON.parse(xhr.responseText);
if (response.status === 'completed') {
console.log('sent');
//console.log(response.filename);
showTranscriptionComplete();
clearInterval(pollInterval); // Stop polling once completed
isTranscribing = false; // Set to false when transcription is complete
}
} else {
showError('An error occurred.');
clearInterval(pollInterval); // Stop polling on error
isTranscribing = false; // Set to false on errors
}
};
xhr.onerror = function() {
showError('Connection error. Please check your network connection and try again.');
clearInterval(pollInterval); // Stop polling on network error
isTranscribing = false; // Set to false on network error
};
xhr.open('GET', `/transcribe/poll_task_status/${taskId}/`, true);
xhr.send();
}, 5000); // Poll every 5 seconds
}
My server-side view returns a JSON response with the status of the task. When the task is completed, I want the page to reload with a specific HTML template that I’ve written.
How can I ensure that the correct HTML template is loaded upon page reload without changing the URL?