Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Ajax with celery task

I am a bit confused on how to proceed with my program. I have a django view that asks the user to input a first name and lastname, then this go to a celery task which process the data and save it to the database. Now, while the task is processing, I want an animated gif to display so the user will know that something is happening.(I've read somewhere here in SO that animated gif is better) then if the task is done, it will redirect to a page that tells the user the process is complete. I have done my research and found out that I should get the task_id and send it to an ajax request.

My problem is how to use ajax. How can I get the task_id from ajax? Or pass the task_id to the ajax request.


EDIT: ** I know this is INCOMPLETE. VERY INCOMPLETE**

Here is some of my codes. It does not do much because I still have to grasp the concept of using ajax. But what I want is when I submit the form, the spinner gif will appear and at the same time, celery will process my tasks. When celery is done processing the task, it will redirect to a page where it says "Success" or anything.

views.py:

def addUser(request):
    if request.method == 'POST':
       addUser = userform(request.POST)
       if addUser.is_valid():
            task = create_user.apply_async((addUser.cleaned_data,), countdown=20)
       return render_to_response('loading.html', {'task_id': task.task_id})
    else:
       addUser = userform()
    return render(request, 'addUser.html', {'addUser':addUser})

addUser.html

<form method="POST">
    {% csrf_token %}
    {{ addUser }}
    <input type="submit" value="Submit">  
</form>

loading.html

<html>
<script>
<head>
<script src="{{ STATIC_URL }}js/jquery-ui.min.js"></script>
<script type="text/javascript">
var formData = task_id; // task id of my celery task

$.ajax({
    url : "templates/success.html", //from what I know, this URL is where the AJAX will go after processing
    type: "POST",
    data : formData,
    success: function(data, textStatus, jqXHR)
    {
        alert("Success")
    },
    error: function (jqXHR, textStatus, errorThrown)
    {
        alert("Failed")
    }
});
</script>

</head>

<body><center>
    {% load static %}
    <img src="{% static 'images/ripple.gif' %}" alt="Hi!" height="150" width="150" />
    </center>
</body>
</html>

tasks.py

@task(ignore_result=True)
def create_user(data):
    user = UserInfo(fname=data['fname'], lname=data['lname'])
    user.save()
    return None

I am not sure where AJAX will go, if it's in the form(addUser.html) or in the loading.html

Please do correct me if I'm wrong. Thank you for the help!

like image 823
predator Avatar asked Jul 29 '15 04:07

predator


1 Answers

The idea is to launch the long running task, when you execute one it returns an AsyncResult object you have to get the "task_id" and return it to the client. The client side (javascript) would make a GET request for example to /check_status/ and pass the "task_id" to the server. The server will ask celery using that task_id and return to the client if the task finished or not.

def view_with_task(request):
     #your code
     # send the task to the worker and get the task_id
     async_result = your_task.delay()
     #code
     ctx = {}
     ctx['task_id'] = async_result.task_id
     return render(tpl, ctx)

from celery import AsyncResult
def check_status(request):
    task_id = request.GET.get('task_id')
    if task_id:
        async_result = AsyncResult(task_id)
        return Jsonresponse({'finish': async_result.ready()})
    return JsonResponse({'finish': False})

BTW, there is a project to do this without pain neither too much code. Thanks

like image 152
Martin Alderete Avatar answered Oct 28 '22 18:10

Martin Alderete