0

I'm trying to make a contact form with python django, at this time it works perfectly, the issue is that I have to wait up to the email message already sends to get the Httpresponse.

Is there any way to return the Httpresponse first and then send the email message?

    send_mail(
    'Subject here',
    data['comentarios'],
    'myemail@gmail.com',
    ['myemail@gmail.com'],
    fail_silently=False,
            )

return HttpResponse('bien') #es menor a 7 digitos   
Bijoy
  • 1,131
  • 1
  • 12
  • 23
El arquitecto
  • 513
  • 2
  • 5
  • 16
  • 1
    you can use any task shecduling mechanism( celery, huey etc), it will resolve your issue. – Cadmus Feb 15 '17 at 03:37
  • use http://michal.karzynski.pl/blog/2014/05/18/setting-up-an-asynchronous-task-queue-for-django-using-celery-redis/ for setup – Vivek Feb 15 '17 at 04:45

1 Answers1

1

I assume you want to let the user see that the email has been sent/the request has been processed immediately after clicking 'Send'. I suggest that you use AJAX to achieve what you are doing.

Thought Process

One thing to note is that you probably want to show a loading gif/svg or something to indicate that the email is in the process of being sent. While the loading gif is shown, proceed with form validation:

  • if everything is ok: proceed with AJAX request send email and return a success/error message indicating whether email was sent.

  • if validation failed: just display error messages


However, if you want to display a message, like 'Thank you', it's something like this:

It should probably look something like this in your JS (if you're using jQuery):

$('#form').on('submit', function(e) {
    e.preventDefault();
    // do some validation
    // if the validation deems the form to be OK - display the 'Thank you!` message first THEN proceed to AJAX request.

    $('#form').append('Thank you!');

    // insert AJAX here
    ...

    // if the validation returns errors - just display errors
    ...        
});

The actual AJAX request:

    // AJAX request
    $.ajax({
        method: 'POST',
        url: '../send_email/', # Just an example - this should be a url that handles a POST request and sends an email as a response
        data: $('#form').serialize(),
        success: function(response) {
            // anything you want
            // an example would be:
            if (response.success) {
                $('#form').append(response.success);
            }
    });

In your views.py:

class SendEmail(View):

    def post(self, request, *args, **kwargs):
        if request.is_ajax():
            send_mail(
                'Subject here',
                data['comentarios'],
                'myemail@gmail.com',
                ['myemail@gmail.com'],
                fail_silently=False,
            )
            return JsonResponse({'success': 'Just a JSON response to show things went ok.'})
        return JsonResponse({'error': 'Oops, invalid request.'})
Community
  • 1
  • 1
Thomas Jiang
  • 1,303
  • 11
  • 16
  • but it is the same, you are right that's what I'm trying to do but if you see the python view, first send the email, than send success data. that exactly What I have, let me show you. success: function(data) { if (data == ''){ alert('telefono malo') } }, failure: function(data) { alert('Error en el envío interno de datos'); } – El arquitecto Feb 16 '17 at 00:54
  • @Elarquitecto ah but note that the "Thank You" is shown BEFORE the AJAX request is made - so you are showing the Thank You before you send the email. In case something goes wrong, you can use the AJAX response to change the response. – Thomas Jiang Feb 16 '17 at 00:59
  • Do you suggest in all validation I use Jquery instead python? it's working now but the issue here is that I'm manage the error in python, look for example this one: try: int(data['telefono']) except: return HttpResponse('badtel'), so if the user type the phone number something like this 12345678A its obviously this is not a number then python send an error whit it suppose to be manage in the frontend. – El arquitecto Feb 16 '17 at 01:27
  • Yes, I would say to put your validation in jQuery - so if anything is wrong with the form, it doesn't get passed to the backend and the error message will show. Only if the data is correct, then the success message will be displayed and the form data will be passed to Django via AJAX. – Thomas Jiang Feb 16 '17 at 01:33
  • In your case where the user types 12345678A - if your validation is correctly done on your frontend, it won't be passed to your server and there will be no need for a `try`...`except`... block to catch the error. Also, you should use `form.is_valid()` and `form.cleaned_data['telfono']` to help you with the backend validation if necessary ( For example, if the user does not have JS enabled, you will have to do server-side validation. However, that will mean you cannot show a message before sending an email unless you use something like celery) – Thomas Jiang Feb 16 '17 at 01:35