Search code examples
djangodjango-formsdjango-email

Django form not saving or emailing as it should


I've built a simple form that should send an email on form submit, as well as save to a table in the database. I've done this by following different tutorials, as I am still learning Django. At the moment, it should be configured to output the email to the console rather than actually send an email, as per the tutorial I followed.

I don't get any errors and the console shows a HTTP 200 success code when the form is posted, so it seems to be working, but since nothing is saved and no email is printed to the console, I'm not sure what is going on.

My models.py:

from __future__ import unicode_literals
from django.db import models
from multiselectfield import MultiSelectField

class Booking(models.Model):
    timeslot = (
        ('EM', 'Early Morning'),
        ('LM', 'Late Morning'),
        ('EA', 'Early Afternoon'),
        ('LA', 'Late Afternoon'),
    )
    services = (
        ('gutters', 'Gutter Cleaning'),
        ('windows', 'Window Cleaning'),
        ('decks', 'Deck Staining'),
        ('painting', 'Painting'),
    )
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    email = models.CharField(max_length=30)
    phone = models.CharField(max_length=30)
    booking_time = models.CharField(max_length=1, choices=timeslot)
    selected_services = MultiSelectField(choices=services)

The relevant part of my views.py:

def booking_new(request):
    form_class = BookingForm

    # new logic!
    if request.method == 'POST':
        form = form_class(data=request.POST)

        if form.is_valid():
            first_name = request.POST.get(
                'first_name'
            , '')
            last_name = request.POST.get(
                'last_name'
            , '')
            email = request.POST.get(
                'email'
            , '')
            phone = request.POST.get(
                'phone'
            , '')
            booking_time = request.POST.get(
                'booking_time'
            , '')
            selected_services = request.POST.get(
                'selected_services'
            , '')
            form_content = request.POST.get('content', '')

            template = get_template('email_template.txt')
            context = {
                'first_name': first_name,
                'last_name': last_name,
                'email': email,
                'form_content': form_content,
            }
            content = template.render(context)

            email = EmailMessage(
                "New contact form submission",
                content,
                "Your website" +'',
                ['youremail@gmail.com'],
                headers = {'Reply-To': contact_email }
            )
            email.send()
            form.save()
            return redirect('booking_new')

    return render(request, 'home/booking_edit.html', {
        'form': form_class,
    })

My forms.py:

from django import forms

from .models import Booking

class BookingForm(forms.ModelForm):

    class Meta:
        model = Booking
        fields = ('first_name', 'last_name', 'email', 'phone', 'booking_time', 'selected_services') 

And the end of my settings.py:

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
DEFAULT_FROM_EMAIL = 'testing@example.com'
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False
EMAIL_PORT = 1025

I'm not getting any errors about missing imports or URLs or templates etc, so I think I have included all the relevant info. As far as I can see everything is configured correctly.

Why when my form is submitted is no email sent, and no record saved to the database?


Solution

  • the console shows a HTTP 200 success code

    This suggests that the form is not valid. If the form was valid, you would redirect after sending the email, so you would see status code 302.

    In the view, you should pass the form to the template instead of the form class. That way you should see any errors rendered in the form template (assuming you use {{ form }}).

    if request.method == 'POST':
        form = form_class(data=request.POST)
        ...
    else:
        form = form_class()  # Blank form for GET request 
    
    return render(request, 'home/booking_edit.html', {
        'form': form,
    })
    

    You may also find it useful to add print statements (e.g. print(form.is_valid()), print(form.errors). The output in the console will help you debug what is happening when the view runs.