0

Question: is it possible to redirect the page while sending the email. It takes 5 to 10 seconds for the mail to be sent. During this time, the page is not doing anything. Users might resubmit the form to prompt a reaction. So I was thinking maybe there's a way to redirect the page right after the object is saved instead of redirecting after the mail is sent. Code below:

@login_required
def handle_order(request, **kwargs):
    ....
    order = form.save(commit=False)
    order.active = True
    order.save()

    # send email to the user, 5-10 seconds waiting time
    kwargs = {...}
    mail_order_detail(**kwargs)

    return redirect('shopping:show-order', order.ref_number)

I've tried to use post_save signal, not working, still have to wait before being redirected

Masklinn
  • 34,759
  • 3
  • 38
  • 57
LD8
  • 176
  • 3
  • 14

4 Answers4

2

if sending mail takes so long with your setup it might be better to use some kind of cronjob or background queue to send mails.

e.g. create a new model for your mails, just insert the mail your want to send in the database and then create a cron job that runs once a minute that sends all mail that are collected in the model.

Bastian
  • 10,403
  • 1
  • 31
  • 40
  • Thanks! Alright, so it's either this or `Celery` async task manager? I'm quite new to Django, is `Celery` necessary for this tast? – LD8 Feb 28 '20 at 01:44
  • I think celery is a bit to much if you just want to send mail... it also depends on your hosting solution .. can you simply add cron tasks? if you are using uwsgi as server it also can do it: https://pypi.org/project/uwsgi-tasks/ – Bastian Feb 28 '20 at 15:36
1

Normally, rather than send an email during the request you would use a mail queue of some sort: create the email in your database or send it to some sort of external job queue, and have an other process or system actually do the mail sending (and retrying as it's pretty common for that to fail) separately.

Masklinn
  • 34,759
  • 3
  • 38
  • 57
  • Thanks Masklinn for your answer, I'm researching on 'cron jobs' right now! Cheers – LD8 Feb 28 '20 at 02:10
1

Seems like a good reason to upgrade your application by using a async task manager such as Celery. There's a very good tutorial seting up celery and the async email sender task on a django app. Once you have celery installed and an instance of it running - check out the tutorial -, you can write a similar function like the following:

from celery import shared_task 

from django.core.mail import send_mail

@shared_task
def send_email_task():
    send_mail('Celery Task Worked!',
    'This is proof the task worked!',
    'support@prettyprinted.com',
    ['sasa@be-breathtaking.net'])

    return None

On your django route you can call the async task, this way your user won't have to wait the e-mail to be sent in order to receive a http response:

from .tasks import send_email_task

def index(request):
    send_email_task.delay()
    return HttpResponse('<h1>EMAIL HAS BEEN SENT WITH CELERY!</h1>')
Kenny Aires
  • 1,338
  • 12
  • 16
  • Thanks Kenny for the straightforward answer and the tutorial link. erm.. Would you say a cron job is better for this task? I'm quite new to Django and I've got 2 answers so... – LD8 Feb 28 '20 at 01:50
  • both solutions would suit well to your need, celery would be a better option as it is more scalable - i.e. you can use the same task queue and more than one server. There's an interesting [answer on this matter here](https://stackoverflow.com/a/16234656/8969084). – Kenny Aires Feb 28 '20 at 18:26
0

Seems like you're in need of an asynchronous operation! (At least, that's my assumption, hah)

Now, what I'm about to suggest may introduce too much overhead to your project (if you're using this for just one operation)

You may be able to utilize a library - Celery - to create asynchronous tasks. With Celery, you can use the apply_async() method, such that the rest of the code in your view can continue to execute whilst the mail is being sent.

https://hackernoon.com/asynchronous-tasks-with-celery-redis-in-django-3e00d3735686

EDIT: Masklinn's solution is probably more time and cost effective!

Wassim Katbey
  • 298
  • 4
  • 9