Creating a Contact Form in Django

In this tutorial, I'm going to show how to create a simple contact form in Django. This form will ask the user for their name, email and message and will send the email with these contents to our specified email address.

For this functionality I'll be creating the files such as forms.py, views.py and urls.py in the project's folder and wont create a separate app for it. But you can put this in an app if you want.

Setting up email delivery

Before we get started, we need to make sure that an email is sent when a user submits the contact form. For a production environment you will need to setup an SMTP server, but that is beyond the scope of this tutorial. Instead we will use the file based email backend provided by Django, which will be perfect for making sure our contact form sends the emails properly.

In your settings.py, add the following.

if DEBUG:
    EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"
    EMAIL_FILE_PATH = os.path.join(BASE_DIR, "sent_emails")

DEFAULT_FROM_EMAIL = '[email protected]' # Can be anything you want.

With EMAIL_BACKEND we tell Django that we want to use it's built-in file-based email backed, and with EMAIL_FILE_PATH we specify the folder name to send the emails to. So with this, you will have a 'sent_emails' folder in your project's root and a .txt file will be created for each email that is sent.

We will use the value of DEFAULT_FROM_EMAIL as the 'From' parameter in the headers of our emails that are sent from the contact form. I will show this later.

Creating the form

Create a forms.py file, if not already created and add this:

from django import forms
from django.core import validators


class ContactForm(forms.Form):
    name = forms.CharField(required=True)
    email = forms.EmailField(required=True)
    message = forms.CharField(widget=forms.Textarea, required=True)
    honeypot = forms.CharField(required=False, widget=forms.HiddenInput, label="Leave empty", validators=[validators.MaxLengthValidator(0)])

So basically, we have a name field, an email field and a message field that the user will see and will have to provide values for, as they are all marked required. The honeypot field is a hidden field, and is used to stop bots from successfully submitting the form. The MaxLengthValidator is a Django's built-in form validator and we've used it to throw an error if the honeypot field contains any value.

Creating the View

Now that our form is created we can create view that will show this form and process it when the user submits it.

First, we need to create the following url pattern in urls.py file.

urlpatterns = [
    ## Other patterns
    url(r'^contact/', views.contact_view, name='contact'),
    ## Other patterns
]

This url pattern will call contact_view if a user goes to 'contact/ ' in the browser. Lets create that view now.

In your views.py, add:

from django.contrib import messages
from django.conf import settings
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.template.loader import get_template
from django.shortcuts import render

from . import forms

def contact_view(request):

    if request.method == 'GET':
        form = forms.ContactForm()
        return render(request, 'contact_form.html', {'form': form})

    elif request.method == 'POST':
        form = forms.ContactForm(request.POST)

        if form.is_valid():

            # Get values of each field
            contact_name = form.cleaned_data['name']
            contact_email = form.cleaned_data['email']
            contact_message = form.cleaned_data['message']

            # Get the template and pass the context values
            template =  get_template('contact_template.txt')
            context = {
                'contact_name': contact_name,
                'contact_email': contact_email,
                'contact_message': contact_message,
            }
            # Get the entire text content with context
            content = template.render(context)

            # Email address that we defined in settings.py
            from_email = settings.DEFAULT_FROM_EMAIL

            # Sending the email
            send_mail(
                'New message from Contact form', # Subject
                content, # Body
                'Contact <{}>'.format(from_email), # From
                ['[email protected]'] # To
            )

            # Add a message to inform the user
            messages.add_message(request, messages.SUCCESS, 'Thanks for your contacting us!')

            # Redirect to the same page
            return HttpResponseRedirect(reverse('contact'))

At first glance it may seem like a lot, but it is really quite straightforward. This is the breakdown of what is going on.

  • def contact_view(request): starts our view, which takes the current request as a parameter.
  • if request.method == 'GET' checks if the request is that of a GET type. Since GET means a simple page load in the browser, we just want to show the form in a template. The next two lines do exactly that. They call ContactForm() which we have created and renders the template contact_form.html (which we will create), along with that form.
  • elif request.method == 'POST' - When the user submits the form, the request will be of POST type. Then the form will be the same ContactForm but with the user supplied fields.
  • if form.is_valid(): - When the user submits the form, and no errors are found, then we can proceed with the supplied values.
  • contact_name, contact_email and contact_message store the values of the supplied field values. The cleaned_data method is what we use to get a field's value after the form has been validated.
  • In the next few lines, we call content_template.txt file and pass in a context dictionary that contains the field values, and then store the result in the content variable. We will create content_template, but it is essentially just a text file that will contain the body of our message in the correct format.
  • Next we actually send the email using the send_mail() function. We define the Subject, the Body, the From email and the To email.
  • We then add a success message using Django's messages framework.
  • And then finally reload the page using HttpResponseRedirect, by doing a reverse on contact which is the name of our contact page's url pattern.

So the above View will show the form on page load, and then send an email with the user's supplied content and reload the page with a success message.

All that is now left to do is to create the two templates we referenced above and display the success message to the user.

Creating the template

In your templates folder, create two files: contact_form.html and contact_template.txt.

contact_form.html

{% extends "base.html" %}

{% block title %}Contact Us{% endblock %}

{% block content %}
    <form action="" method="POST">
        {{ form.as_p }}
        {% csrf_token %}
        <input type="submit" class="button">
    </form>
{% endblock %}

Just a basic template with a form. Notice the form's method attribute is set to POST. That's how our view above acts differently when user submits the form.

contact_template.txt

From:
{{ contact_name }}

Email:
{{ contact_email }}

Message:
{{ contact_message }}

As you can see, the contact_name, contact_email and contact_message are the template tags that we pass in our view.

Displaying user messages

In our view we added the success message: "Thanks for contacting us!", but currently we aren't displaying that message anywhere. You can add the code for that in contact_form.html to display this message, but I'm going to put it in base.html that the contact_form.html extends.

An example of what base.html might look like, along with the message tags.

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{% block title %}{% endblock %}</title>
    </head>
    <body>
        {% if messages %}
            {% for message in messages %}
                <div class="{{ message.tags }}">
                    {{ message }}
                </div>
            {% endfor %}
        {% endif %}
        {% block content %}{% endblock %}
    </body>
</html>

Final Product

We are done with the tutorial. Following are the screenshots of the form and the email text file.

On page load with values entered:

Contact Form 1

When form is successfully submitted:

Contact Form 2

The .txt file for the email:

Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: New message from Contact form
From: Contact <noreply@yourwebsite.com>
To: [email protected]
Date: Sat, 10 Jun 2017 12:21:32 -0000

From:
Jon

Email:
[email protected]

Message:
Till what time are you open?

-------------------------------------------------------------------------------

Hope you are able to get the same. Thanks!

blog comments powered by Disqus