Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect and Pass Celery Task Data with Django

Tags:

django

celery

I would like to build with django-celery a web-server that:

  1. Accepts data from user on the page /input/
  2. Starts a Celery task to process them
  3. Redirects to the page /wait/, where user waits until the processing is completed
  4. When the task is completed, automatically redirects to the page /result/

Currently I got stuck with the code (simplified):

views.py:

def input(request):
    # Read form data to 'parameters'
    task = process_user_input.delay(parameters)
    response = HttpResponseRedirect("/wait")
    response.session['task'] = task
    return response

def wait(request):
    task = request.session.get('task', None)
    while task.state not in ('SUCCESS', 'FAILURE'):
        time.sleep(0.1)
    return HttpResponseRedirect("/result")

def result(request):
    # 

urls.py:

urlpatterns = patterns('',
    url(r'^input/$', views.input, name = 'input'),
    url(r'^wait/$', views.wait, name = 'wait'),
    url(r'^result/$', views.result, name = 'result'),
)

This, however, does not work, as 'HttpResponseRedirect' object has no attribute 'session'. I also tried to use render function, but it only loads corresponding template without calling the view function.

Can someone help me to fix the code so that it fulfils my goal?

like image 436
Roman Avatar asked Nov 19 '25 19:11

Roman


1 Answers

After some research I came to conclusion I came to conclusion that the required functionality is not provided by django, as one cannot cannot render pages asynchronously (and, as a result, cannot render and redirect at the same time). Therefore, I decided to get rid of the /wait/ page. My views.py now looks like this:

from my_app.forms import InputForm
from mysite.tasks import process_user_input

def input(request):
    form = InputForm()
    # Read form data to 'parameters'
    task = process_user_input.delay(parameters)
    while task.state not in ('SUCCESS', 'FAILURE'):
        time.sleep(0.1)
    if task.failed():
        # Insert error message and return to the input form
        render(request, 'my_app/input.html', {'form': form})
    return HttpResponseRedirect("/result")

def result(request):
    # 

The waiting message I had to implement using Javascript with jQuery in input.html:

<div id="form_container">
    <!--The form (with id="input_form") is here-->
</div>
<div id="hidden_section" style="display: none;">
    <!--The please-wait-message is here-->
</div>

<script>
$(document).ready(function () {
    $("#input_form").submit(function () {
        $("#form_container").attr("style", "display: none");
        $("#hidden_section").attr("style", "display: block");
        return true;
    });
});
</script>

As a result, after submitting the form, a user remains on the /input/ page, but is seeing the please-wait-message until the task is completed or an error occurs.

like image 71
Roman Avatar answered Nov 22 '25 17:11

Roman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!