Q:

Make celery wait for task to finish

I want celery to wait for a specific task to finish, therefor I installed the celery-results-backend beside celery itself. But I don't understand how I have to write my task call in order to wait as I currently get the following error:
example_task() missing 1 required positional argument: 'user_pk'

views.py
def example(request):
    user = request.user
    if request.method == 'GET':
        result = example_taks.apply_async(user_pk=user.pk)
        result_output = result.wait(timeout=None, interval=0.5)
        return redirect('something')
    else:
        args = {'user': user}
        return redirect(reverse('something'), args)

at my tasks.py:
def example_task(user_pk):
    user = User.objects.get(pk=user_pk)
    try:
       ...

previously I called the talks like that: 
def example(request):
    user = request.user
    if request.method == 'GET':
    example_task.delay(request.user.pk)
    ...

This was working fine but did not wait for task to finish.
If i Just do:
result = allocate_new_bch_address.apply_async(request.user.pk)

I also get a error:
example_task() argument after * must be an iterable, not UUID
thanksful for any advice here.

A:

First, you're using apply_async() wrong. The function accepts your task's arguments packed as a tuple (args) and dictionary (kwargs) as seen here. This is because you can specify additional parameters that define how the task should run.  On the other hand, delay() only accepts your task's args and kwargs. delay() is sufficient in most cases.
You can either do this:
 example_taks.apply_async(kwargs={"user_pk":user.pk})

Or this:
example_tasks.delay(user_pk=user.pk)

You can also use positional arguments but I would  recommend using kwargs when possible.
Second, waiting for an async task as soon as submitting it defeats the purpose of Celery. To wait for a task to finish you need to call get() on the result:
result = example_tasks.apply_async(kwargs={"user_pk":user.pk})
result_output = result.get()

