0

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?

Jake Rankin
  • 714
  • 6
  • 22
  • Please add code for EmailMessage – Marcell Erasmus Aug 23 '18 at 14:22
  • @MarcellErasmus The EmailMessage code is near the bottom of the views.py snippet I pasted – Jake Rankin Aug 23 '18 at 14:28
  • Note that you should use `form.cleaned_data` instead of `request.POST` to access the data from the form. See the [example in the docs](https://docs.djangoproject.com/en/2.1/topics/forms/#field-data). – Alasdair Aug 23 '18 at 14:53
  • @Alasdair, I will modify my form to do that. Was just following the tutorial which doesn't specify that, which is a shame because it was good otherwise. – Jake Rankin Aug 23 '18 at 15:01

1 Answers1

1

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.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • Hmm, I tried this but the page does not load at all, and I get an error "Ensure this value has at most 1 character (it has 2).", which seems odd as I have no such limits on any of my form fields. – Jake Rankin Aug 23 '18 at 14:41
  • It looks like the error might be coming from `booking_time = models.CharField(max_length=1, choices=timeslot)`. I don't know what code you running or what you mean by *the page does not load at all*, so I can't help with that. – Alasdair Aug 23 '18 at 14:47
  • I thought it was referring to the textfield above. That field is a drop down box, it's only possibly to have one item selected. How it it possible that django thinks two items are selected in that field, causing the error? See https://imgur.com/a/5vqQ4az - – Jake Rankin Aug 23 '18 at 14:49
  • You've misunderstood `max_length`. `EM` is two characters long, so it's not a valid choice for a field with `max_length=1`. – Alasdair Aug 23 '18 at 14:52
  • Got it working. At least the email is put out to console. However it seems the form data is still not saved to the database as it should be. form.save is called correctly, so I'm not sure why this would be? – Jake Rankin Aug 23 '18 at 15:00
  • I can't spot anything in code that explains why `form.save()` isn't working. – Alasdair Aug 23 '18 at 15:16