Адрес контактной электронной почты часто указан в самом нижнем колонтитуле на сайте. Пользователь должен не только отыскать адрес электронной почты, но еще и самостоятельно отправить письмо. Хотя такой способ организации обратной связи ни в коем случае нельзя назвать плохим, он все-таки требует от пользователя гораздо больше усилий, чем необходимый минимум.
Клиенту нужно угождать, ценить его время — так давайте попробуем облегчить процесс отправки электронного письма! Нам в этом поможет контактная форма, автоматически отправляющая письмо в техподдержку сайта. Хотя решение задачи на первый взгляд может показаться сложным, почти весь функционал успешно создается с помощью фреймворка Python Django.
Статья даст ответы на следующие вопросы, волнующие каждого начинающего Python Django веб-разработчика.
- Как создать поля контактной формы Django?
- Как добавить форму в HTML шаблон?
- Как добавить бэкенд электронной почты Django?
1. Создание контактной формы в forms.py
Путь к файлу: env > mysite > main > forms.py
from django import forms
class ContactForm(forms.Form):
first_name = forms.CharField(max_length=50)
last_name = forms.CharField(max_length=50)
email_address = forms.EmailField(max_length=150)
message = forms.CharField(widget=forms.Textarea,
max_length=2000)
Чтобы создать контактную форму, необходимо в файле forms.py
унаследовать от базового класса forms.Form
класс контактной формы. Она будет называться ContactForm
и содержать поля для запроса основной контактной информации о клиенте перед отправкой сообщения в техподдержку. При создании Django-приложения файл forms.py
не создаётся автоматически, поэтому создайте его собственноручно в директории приложения main
(там, где находится файл models.py
).
Внутри класса ContactForm(forms.Form)
определите поля first_name
и last_name
(имя и фамилия), воспользовавшись классом CharField
из модуля form
— так создаются символьные (текстовые) поля. Для каждого из них установите атрибуту max_length
значение 50: теперь форма ограничит допустимый ввод в одно поле до 50 символов. Затем добавьте новое поле email_address
с помощью класса EmailField
из модуля form
— это специфическое поле, перед отправкой формы автоматически проверяющее соответствие ввода пользователя формату адреса электронной почты. Наконец, добавьте поле message
с помощью того же класса CharField
, но с виджетом forms.Textarea
, указывающим, что данное поле будет отрисовываться в HTML как принимающее длинный текст в стиле абзаца.
Сохраните все изменения в файле forms.py
!
2. Создание представления для страницы с формой во views.py
Путь к файлу: env > mysite > main > views.py
from django.shortcuts import render, redirect
from .forms import ContactForm
from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse
def homepage(request):
return render(request, "main/home.html")
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
subject = "Пробное сообщение"
body = {
'first_name': form.cleaned_data['first_name'],
'last_name': form.cleaned_data['last_name'],
'email': form.cleaned_data['email_address'],
'message': form.cleaned_data['message'],
}
message = "\n".join(body.values())
try:
send_mail(subject, message,
'[email protected]',
['[email protected]'])
except BadHeaderError:
return HttpResponse('Найден некорректный заголовок')
return redirect("main:homepage")
form = ContactForm()
return render(request, "main/contact.html", {'form': form})
Откройте файл views.py, импортируйте в него ряд объектов, которые нам пригодятся.
- Функция
send_mail
(отправка сообщения) и классBadHeaderError
(исключение для перехвата) из модуляdjango.core.mail
. - Функции
render
(отрисовка страницы на основе шаблона и данных контекста) иredirect
(перенаправление браузера на другую страницу) из модуляdjango.shortcuts
. - Класс
HttpResponse
(ответ на HTTP-запрос к серверу от браузера пользователя) из модуляdjango.http
. - Класс
ContactForm
из только что созданного нами модуляforms.py
.
Далее создайте функцию-представление contact(request)
и укажите один блок с условием, которое проверяет соответствие клиентского запроса об отправке формы HTTP-методу POST. Другими словами, если HTTP-запрос от пользователя на отправку контактной формы использует именно метод POST — то начинается выполнение следующих строчек кода.
- Создайте переменную
form = ContactForm(request.POST)
, ссылающуюся в качестве значения на экземпляр класса, а в качестве аргумента передайте этому классу данные, только что отправленные пользователем к вам на сервер с помощью HTTP-запроса методом POST. - Снова напишите блок условия
if form.is_valid()
, который будет содержать действия, выполняющиеся только в случае успешной проверки ввода пользователя, ведь в случае некорректности введенных пользователем данных нам не стоит отправлять сообщение в техподдержку. - Приступим к созданию сообщения для отправки на электронную почту. Темой сообщения (переменная
subject
) будет текст “Пробное сообщение”, а телом сообщения (переменнаяbody
) — поочередно все поля формы, заполненные правильно. Получить к ним доступ можно с помощью обращения к атрибуту проверенной формы с “чистыми” даннымиform.cleaned_data[‘form_field’]
. Атрибутcleaned_data
доступен только внутри блока условияif form.is_valid()
. - Форматируем текст сообщения. Для этого с помощью выполнения метода
“\n”.join(body.values())
объединим в один текст и разделим символом новой строки все значения ключей словаряbody.values()
. Получившийся результат сохраняем в переменнуюmessage
. - Теперь можно отправлять сообщение. Воспользуемся функцией
send_mail(subject, message, 'адрес отправителя', 'адрес получателя')
. - В качестве адресов электронной почты отправителя и получателя устанавливаем
[email protected]
, чтобы текст письма был виден в терминале, так как это удобно для тестирования. - Теперь нужно перехватить ошибку плохого заголовка
BadHeaderError
, чтобы предотвратить вставку злоумышленниками дополнительных заголовков электронной почты. Если обнаружен “плохой заголовок”, то представление вернет клиентуHttpResponse
с текстом “Найден некорректный заголовок”. - Если форма отправлена правильно, реализуем перенаправление клиента на домашнюю страницу приложения с помощью функции
redirect('main:homepage')
. Если у вашего приложения нет главной страницы, то создайте для неё URL-адрес с названием “homepage” в файлеurls.py
. - В конце концов, нам необходимо реализовать отправку в браузер пользователя той формы, которую он будет заполнять. Для этого вне любых блоков условий, на самом первом уровне функции, создайте переменную
form = ContactForm()
. С помощью возврата представлением результата работы методаrender(request, “main/contact.html”, {‘form’: form})
предоставьте браузеру пользователя страницу с шаблономcontact.html
и контактной формой в качестве контекста для этого шаблона.
3. Создание URL-пути для страницы с формой в urls.py
Путь к файлу: env > mysite > main > urls.py
from django.urls import path
from . import views
app_name = "main"
urlpatterns = [
path("", views.homepage, name="homepage"),
path("contact", views.contact, name="contact"),
]
Теперь добавим URL страницы с контактной формой в urls.py
нашего приложения. Если же вы используете существующий шаблон с указанным ранее URL, то пропустите этот шаг.
4. Создание шаблона contact.html
Путь к файлу: env > mysite > main > templates > main > contact.html
<!--Contact form-->
<div style="margin:80px">
<h1>Контакты</h1>
<h4>Напишите нам, если у вас есть вопросы</h4>
<p>
Пожалуйста, напишите свое имя, адрес электронной почты и сообщение.
</p>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Отправить</button>
</form>
</div>
Откройте файл contact.html
или файл шаблона по вашему выбору и пропишите HTML-тег <form></form>
под текстом. Добавьте к этому тегу атрибут method=”POST”
, чтобы форма использовала метод POST при отправке данных обратно в функцию-представление contant(request)
. Внутри элемента формы вложите шаблонный тег Django {%csrf_token%}
, чтобы предотвратить подделку формы злоумышленниками. Это очень важная строчка кода, которая позволит вашему Django-проекту безопасно отправлять информацию.
После CSRF-токена обратитесь к полям формы ContactForm
, находящимся в контексте шаблона. Чтобы обернуть все поля в теги <p></p>
, используйте {{form.as_p}}
. Вы также можете получить доступ ко всем полям по отдельности, используя формат {{form.name_of_field}}
.
Наконец, добавьте кнопку отправки формы непосредственно перед закрывающим тегом </form>
.
5. Добавление Email backend в настройки проекта
Путь к файлу: env > mysite > main > settings.py
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
Если включен режим разработчика, то письмо отправляется в CLI (интерфейс командной строки), а не на почтовый ящик.
В нижней части файла settings.py
добавьте вышеописанную константу EMAIL_BACKEND
, так как именно она устанавливает командную строку/терминал в качестве почтового бэкенда Django для целей тестирования, но со временем стоит заменить настройку почтового бэкенда на реальный сервис отправки электронной почты.
6. Отправка пробного электронного письма в CLI
macOS Terminal/Windows Command Prompt
____________________________________________________________________
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Пробное сообщение
From: [email protected]
To: [email protected]
Date: Wed, 05 Feb 2020 00:04:43 -0000
Message-ID: [123456789@DESKTOP]
Джон
Смит
[email protected]
Привет, хочу задать вопрос...
____________________________________________________________________
Наконец-то в браузере можно заполнить и отправить контактную форму. Перейдите по ссылке http://127.0.0.1:8000/contact. После отправки формы на сервер браузер будет мгновенно перенаправлен на домашнюю страницу приложения main
.
Но как же узнать, что электронное письмо отправилось корректно?
Перейдите в командную строку или терминал, и там вы увидите примерно то же самое сообщение, что написано в блоке кода вверху параграфа. Электронные письма можно прочитать прямо в CLI из-за того, что мы настроили почтовый бэкенд Django на вывод в консоль, а не на фактическую отправку письма.
7. Что делать, если ‘django.core.mail.backends.console.EmailBackend’ не работает?
Если бэкенд электронной почты Django в настройках не работает, то выполните следующие шаги.
- Проверьте, нет ли орфографических ошибок.
- Убедитесь, что значение константы
EMAIL_BACKEND
является строкой, обрамлённой кавычками. - Если вышеописанное не является причиной ошибки, то перейдите к файлу
views.py
и убедитесь, что функцияsend_email
и классBadHeaderError
импортированы изdjango.core.mail
, аHttpResponse
импортирован изdjango.http
в верхней части файла. - Наконец, убедитесь, что вы создали блоки
try
иexcept
в функции-представленииcontact(request)
из файлаviews.py
, иначе данная функция не будет работать должным образом и письмо не будет отправлено.
env > mysite > main > views.py
from django.shortcuts import render, redirect
from .forms import ContactForm
from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse
def homepage(request):
return render(request, "main/home.html")
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
subject = "Пробное сообщение"
body = {
'first_name': form.cleaned_data['first_name'],
'last_name': form.cleaned_data['last_name'],
'email': form.cleaned_data['email_address'],
'message': form.cleaned_data['message'],
}
message = "\n".join(body.values())
try:
send_mail(subject, message,
'[email protected]',
['[email protected]'])
except BadHeaderError:
return HttpResponse('Найден некорретный заголовок')
return redirect("main:homepage")
form = ContactForm()
return render(request, "main/contact.html", {'form': form})
Читайте также:
- 3 важных рекомендации Django-программистам
- Python Django: как изменить страницу ошибки 404?
- Python для начинающих: какая разница между tuple, list и set?
Читайте нас в Telegram, VK и Яндекс.Дзен
Оригинал статьи Ordinary Coders: Build a Django Contact Form with Email Backend