Капча и защита формы в Django: пошаговая инструкция
За 30–40 минут вы поставите reCAPTCHA v2 на форму обратной связи в Django 5.x, включите CSRF-защиту и добавите honeypot-поле, чтобы отсеять ботов без раздражения живых людей.

К концу этой инструкции у вас будет форма обратной связи, которую боты не смогут отправлять пачками: с флажком reCAPTCHA от Google, скрытым honeypot-полем и правильно включённой CSRF-защитой. Времени уйдёт примерно 30–40 минут, если проект на Django уже запускается локально. Всё показано для Django 5.x и пакета django-recaptcha 4.x.
Что нужно иметь до начала
Проверьте это до того, как начнёте править код — иначе застрянете на середине.
- Работающий проект на Django 5.x, который открывается по
python manage.py runserver. - Python 3.10 или новее (требование django-recaptcha 4.x).
- Аккаунт Google и доступ к консоли reCAPTCHA, чтобы получить пару ключей: сайт-ключ и секретный ключ.
- Установленная библиотека
requestsне нужна — django-recaptcha ходит к Google сам.
Регистрируя сайт в консоли reCAPTCHA, выберите тип reCAPTCHA v2 → «Я не робот» (флажок). В поле доменов на время разработки добавьте localhost и 127.0.0.1, иначе капча на локальной машине покажет ошибку домена.
Шаг 1. Установите пакет
pip install django-recaptcha
Затем добавьте приложение в INSTALLED_APPS в файле настроек проекта:
# settings.py
INSTALLED_APPS = [
# ... ваши приложения
"django_recaptcha",
]
Проверка: запустите python manage.py runserver. Сервер должен подняться без ошибки ModuleNotFoundError. Если приложение называется иначе — сверьтесь с актуальным README пакета, имя модуля менялось между старыми и новыми версиями.
Шаг 2. Пропишите ключи reCAPTCHA
Ключи из консоли Google положите в настройки. Не хардкодьте секретный ключ прямо в репозитории — читайте его из переменной окружения.
# settings.py
import os
RECAPTCHA_PUBLIC_KEY = os.environ.get("RECAPTCHA_PUBLIC_KEY", "YOUR_SITE_KEY")
RECAPTCHA_PRIVATE_KEY = os.environ.get("RECAPTCHA_PRIVATE_KEY", "YOUR_SECRET_KEY")
Публичный (сайт) ключ попадёт в HTML и виден всем — это нормально. Секретный ключ используется только на сервере при проверке ответа и наружу выходить не должен.
Проверка: в консоли Python внутри python manage.py shell выполните from django.conf import settings; settings.RECAPTCHA_PUBLIC_KEY — вернётся ваш ключ, а не заглушка.
Шаг 3. Добавьте поле капчи в форму
Пакет даёт готовое поле формы. Пример формы обратной связи с honeypot-полем в придачу:
# forms.py
from django import forms
from django_recaptcha.fields import ReCaptchaField
from django_recaptcha.widgets import ReCaptchaV2Checkbox
class ContactForm(forms.Form):
name = forms.CharField(max_length=100, label="Имя")
email = forms.EmailField(label="E-mail")
message = forms.CharField(widget=forms.Textarea, label="Сообщение")
# Скрытая ловушка для ботов. Живой пользователь её не видит,
# бот заполняет все поля подряд.
website = forms.CharField(
required=False,
widget=forms.HiddenInput,
label="",
)
captcha = ReCaptchaField(widget=ReCaptchaV2Checkbox())
def clean_website(self):
# Если honeypot заполнен — это бот.
if self.cleaned_data.get("website"):
raise forms.ValidationError("Спам-фильтр отклонил отправку.")
return self.cleaned_data["website"]
Поле website — приманка. Его прячет HiddenInput, поэтому человек его не трогает. Автоматические скрипты заполняют все поля формы, включая скрытые, и на этом попадаются.
Проверка: импортируйте форму в shell — from myapp.forms import ContactForm; ContactForm(). Если импорт прошёл без ошибок, поле капчи собралось.
Шаг 4. Обработайте форму во вью
# views.py
from django.shortcuts import render, redirect
from .forms import ContactForm
def contact_view(request):
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
# Капча и honeypot прошли проверку — обрабатываем данные.
# Здесь отправка письма или сохранение в базу.
return redirect("contact_success")
else:
form = ContactForm()
return render(request, "contact.html", {"form": form})
Вся проверка капчи прячется внутри form.is_valid(): поле ReCaptchaField само отправляет запрос к Google с секретным ключом и проваливает валидацию, если ответ отрицательный. Отдельно вызывать проверку не нужно.
Шаг 5. Выведите форму в шаблоне
CSRF-защита в Django включена по умолчанию через CsrfViewMiddleware. Ваша задача — не отключать её и поставить тег {% csrf_token %} внутри формы.
<!-- contact.html -->
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Отправить</button>
</form>
Виджет капчи подтягивает нужный JavaScript от Google автоматически — отдельный тег <script> добавлять не надо. Если у вас включён Content Security Policy, разрешите загрузку с www.google.com и www.gstatic.com, иначе флажок не отрисуется.
Проверка: откройте страницу в браузере. Под полями появится блок «Я не робот» с флажком. Отправьте форму без установки флажка — валидация не пройдёт и покажется ошибка под капчей.
Капча защищает от массовой автоматики, а не от целевой атаки. Против точечного спама руками она бессильна — там нужны rate limiting и модерация. Не путайте задачи.
Если не получилось
Самые частые ошибки, которые вы реально увидите:
- Флажок капчи не появляется, в консоли браузера «Invalid domain for site key». Домен, с которого открыта страница, не добавлен в настройках сайта в консоли reCAPTCHA. Добавьте
localhostи127.0.0.1для разработки. - Форма всегда невалидна, ошибка у поля
captcha: «Неверная капча». Перепутаны ключи: публичный и секретный местами, или секретный из другого сайта reCAPTCHA. СверьтеRECAPTCHA_PRIVATE_KEYс секретным ключом того же сайта, что и публичный. - 403 Forbidden, «CSRF verification failed». В шаблоне нет
{% csrf_token %}внутри тега<form>, либо форма отправляется на другой домен. Добавьте токен и проверьтеmethod="post". - Ошибка
ModuleNotFoundError: No module named 'django_recaptcha'. Пакет не установлен в активном виртуальном окружении. Активируйте venv и повторитеpip install django-recaptcha. - Капча работает на локали, но падает в тестах. В тестах Google недоступен. Установите переменную окружения
RECAPTCHA_TESTING=True— пакет поддерживает тестовый режим, при котором капча считается пройденной. Уточните точное имя переменной в README вашей версии пакета.
Что делать дальше
Капча закрывает форму от ботов, но не от частых отправок с одного адреса. Следующий шаг — ограничение частоты: подключите django-ratelimit и повесьте лимит на вью (например, 5 отправок в минуту с одного IP). Отдельная тема — переход на reCAPTCHA v3 без флажка, где вместо клика оценивается поведение и вы сами решаете, с какого балла блокировать; здесь мы её не разбирали. В продакшене следите за долей отклонённых honeypot-срабатываний: резкий рост часто значит, что вас нашёл новый спам-скрипт.
Редактор изображений: Убрать лишнее, заменить фон, добавить объект, расширить кадр — на вашем изображении.
Спросить за 20 ₽Источники: django-recaptcha — репозиторий и README, Django docs — Cross Site Request Forgery protection
Частые вопросы
У меня Django 4.2, а не 5.x — инструкция подойдёт?
Флажок не появляется, хотя ключи прописаны верно. Что не так?
Обязательно ли использовать сторонний пакет, или можно проверять капчу вручную?
Нужен ли honeypot, если уже стоит reCAPTCHA?
Стоит ли ставить капчу на все формы сайта?
Отключать ли CSRF-защиту, раз есть капча?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.