Форма обратной связи на Django: с чего начать
Пошаговая сборка рабочей формы обратной связи на Django 5.x: от объявления Form до отправки письма и вывода сообщения об успехе. Займёт около часа.

К концу этого гайда у вас будет страница с формой обратной связи: посетитель вводит имя, email и текст, нажимает кнопку, данные проверяются на сервере, письмо уходит вам на почту, а пользователь видит сообщение «Спасибо, сообщение отправлено». Всё на штатных инструментах Django, без сторонних пакетов. На сборку уйдёт примерно час, если проект уже создан.
Материал для Django 5.x (проверено на 5.0 и 5.1) и Python 3.10+. В более старых версиях API форм и отправки почты тот же, отличаться могут только настройки проекта.
Что нужно иметь до начала
Прежде чем писать код, убедитесь, что у вас на месте:
- Установленный Django 5.x. Проверьте командой
python -m django --version— должна вывестись версия 5.x. - Уже созданный проект и хотя бы одно приложение. Если приложения нет, создайте:
python manage.py startapp feedback, и добавьте'feedback'вINSTALLED_APPSвsettings.py. - Настроенные URL-маршруты проекта — файл
urls.py, который вы уже редактировали хотя бы раз. - Понимание, куда должны приходить письма. На этапе разработки почта будет печататься в консоль, реальную отправку подключим в конце.
Если чего-то не хватает — сначала доведите проект до состояния, когда открывается хотя бы одна ваша страница. Форма — это надстройка над уже работающим проектом, а не первый файл в нём.
Шаг 1. Объявляем форму
Django предлагает два класса: forms.Form — форма, не привязанная к модели, и forms.ModelForm — форма поверх модели базы данных. Для обратной связи, где сообщения не обязательно хранить в базе, берём обычный Form. Создайте файл feedback/forms.py:
# feedback/forms.py — Django 5.x
from django import forms
class FeedbackForm(forms.Form):
name = forms.CharField(
label="Ваше имя",
max_length=100,
)
email = forms.EmailField(
label="Email для ответа",
)
message = forms.CharField(
label="Сообщение",
widget=forms.Textarea,
max_length=2000,
)
Проверка: файл сохраняется без ошибок импорта. Пока визуально проверить нечего — форму мы ещё не показали.
Поле EmailField само проверит, что введён корректный адрес, а max_length ограничит длину и в браузере, и на сервере. Валидация на сервере сработает даже если пользователь обойдёт браузерную проверку — это одна из причин делать форму средствами Django, а не голым HTML.
Шаг 2. Пишем представление
Представление (view) должно обрабатывать два случая: GET — показать пустую форму, POST — принять и проверить данные. Откройте feedback/views.py:
# feedback/views.py — Django 5.x
from django.shortcuts import render, redirect
from django.contrib import messages
from django.core.mail import send_mail
from .forms import FeedbackForm
def feedback_view(request):
if request.method == "POST":
form = FeedbackForm(request.POST)
if form.is_valid():
name = form.cleaned_data["name"]
email = form.cleaned_data["email"]
message = form.cleaned_data["message"]
send_mail(
subject=f"Обратная связь от {name}",
message=f"От: {name} <{email}>\n\n{message}",
from_email=None, # возьмётся из DEFAULT_FROM_EMAIL
recipient_list=["admin@example.com"],
)
messages.success(request, "Спасибо, сообщение отправлено.")
return redirect("feedback")
else:
form = FeedbackForm()
return render(request, "feedback/feedback.html", {"form": form})
Проверка: после того как добавите шаблон и маршрут (следующие шаги), GET-запрос покажет форму, а не ошибку 500.
Обратите внимание на redirect после успешной отправки. Это шаблон PRG (Post/Redirect/Get): после POST мы перенаправляем на GET, чтобы обновление страницы браузером не отправляло письмо повторно.
Валидные данные вform.cleaned_dataуже приведены к нужным типам и очищены. Никогда не берите значения напрямую изrequest.POST— это сырой ввод без проверки.
Шаг 3. Добавляем маршрут
В urls.py приложения (создайте файл feedback/urls.py, если его нет) пропишите путь:
# feedback/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("feedback/", views.feedback_view, name="feedback"),
]
Затем подключите его в корневом urls.py проекта через include:
# проект/urls.py
from django.urls import path, include
urlpatterns = [
path("", include("feedback.urls")),
# ... остальные маршруты
]
Проверка: запустите python manage.py runserver и откройте http://127.0.0.1:8000/feedback/. Пока увидите ошибку про отсутствующий шаблон — это нормально, шаблон сделаем следующим.
Шаг 4. Шаблон с формой и CSRF-токеном
Создайте файл feedback/templates/feedback/feedback.html. Путь важен: Django ищет шаблоны в папке templates внутри приложения, если в settings.py у TEMPLATES включено APP_DIRS: True (в новом проекте включено по умолчанию).
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Обратная связь</title>
</head>
<body>
{% if messages %}
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
{% endif %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Отправить</button>
</form>
</body>
</html>
Проверка: обновите страницу — появятся три поля с подписями и кнопка «Отправить».
Тег {% csrf_token %} обязателен: без него POST-запрос вернёт ошибку 403. Django защищает формы от подделки межсайтовых запросов, и токен — часть этой защиты. {{ form.as_p }} отрисует каждое поле в отдельном абзаце <p> — это самый быстрый способ увидеть результат. Верстать поля вручную можно позже.
Шаг 5. Настраиваем отправку почты
На этапе разработки не подключайте реальный SMTP. Настройте вывод писем в консоль — в settings.py:
# settings.py — только для разработки
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
DEFAULT_FROM_EMAIL = "noreply@example.com"
Проверка: заполните форму корректными данными и нажмите «Отправить». В терминале, где запущен runserver, появится текст письма с темой и телом. Сверху страницы — «Спасибо, сообщение отправлено».
Для боевого сервера консольный бэкенд замените на SMTP. Точные имена настроек (EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, EMAIL_USE_TLS) и их актуальный список смотрите в документации Django по отправке почты — вписывать сюда параметры конкретного почтового провайдера смысла нет, они у всех разные. Пароль от почты держите не в settings.py, а в переменной окружения.
Соответствие настроек: что куда
| Настройка | Значение для разработки | Что делает |
|---|---|---|
EMAIL_BACKEND | ...console.EmailBackend | Печатает письма в консоль вместо реальной отправки |
DEFAULT_FROM_EMAIL | noreply@example.com | Адрес отправителя, если from_email=None |
APP_DIRS (в TEMPLATES) | True | Разрешает искать шаблоны внутри приложений |
Если не получилось
Пять ошибок, которые встречаются чаще всего:
- Forbidden (403) CSRF verification failed — вы забыли
{% csrf_token %}внутри тега<form>. Добавьте его сразу после открывающего тега формы. - TemplateDoesNotExist: feedback/feedback.html — шаблон лежит не там. Проверьте путь:
feedback/templates/feedback/feedback.html, папка приложения повторяется дважды. - Reverse for 'feedback' not found — в
redirect("feedback")используется имя маршрута, а вы не задалиname="feedback"вpath. Сверьте имена. - Письмо не приходит, но ошибок нет — при консольном бэкенде письма не уходят на почту, а печатаются в терминал. Смотрите в окно с
runserver. - Форма отправляется, но данные не проходят валидацию — проверьте, что метод формы
method="post", а во view вы создаёте форму какFeedbackForm(request.POST), а не пустую.
Что делать дальше
Базовая форма работает. Следующие шаги, когда будете готовы:
- Подключить реальный SMTP через настройки почты и переменные окружения — документация Django, раздел «Sending email».
- Добавить защиту от спама: скрытое поле-ловушку (honeypot) или reCAPTCHA. Штатного антиспама в Django нет, это отдельная задача.
- Если нужно хранить обращения — перевести форму на
ModelFormи сохранять в базу черезform.save(). Это отдельная тема, здесь мы сознательно обошлись без модели. - Причесать вёрстку: заменить
{{ form.as_p }}на ручную отрисовку полей или подключить пакет для оформления форм.
Мотивационное письмо и эссе: Поступление, стипендии, гранты, обмен
Спросить за 25 ₽Источники: Django: Working with forms, Django: Sending email
Частые вопросы
У меня Django 4.2, а не 5.x — код подойдёт?
Обязательно ли делать модель и хранить сообщения в базе?
Письмо не приходит на реальную почту, что не так?
Почему при отправке формы вылезает ошибка 403?
Нужна ли отдельная защита от спама?
Можно ли обойтись без redirect после отправки?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.