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

К концу этой инструкции у вас будет форма обратной связи на Django 5.x с тремя слоями защиты: встроенным CSRF-токеном, скрытым honeypot-полем и капчей Google reCAPTCHA v2 (галочка «Я не робот»). На всё уйдёт 30-40 минут, если проект уже запускается локально. Спам от простейших ботов пропадёт сразу, а более сложные упрутся в капчу.
Мы не будем разбирать, как reCAPTCHA считает поведение пользователя внутри — это тема отдельного разбора. Здесь только подключение и типичные места, где новички ломают форму.
Что нужно до начала
Проверьте, что у вас есть всё из списка. Если чего-то не хватает, вы узнаете об этом сейчас, а не на шаге с шаблоном.
- Python 3.10+ и установленный Django 5.x (
python -m django --versionпокажет версию). - Работающий проект:
python manage.py runserverотдаёт страницу без ошибок. - Аккаунт Google для регистрации ключей reCAPTCHA.
- Пакет
django-recaptcha— поставим на первом шаге.
reCAPTCHA v2 требует два ключа: сайта (публичный, уходит в HTML) и секретный (остаётся на сервере). Получить их можно в консоли reCAPTCHA, выбрав тип «reCAPTCHA v2» → «Флажок». Домен для локальной разработки — localhost и 127.0.0.1.
Шаг 1. Ставим пакет
В активированном виртуальном окружении:
pip install django-recaptchaПакет django-recaptcha даёт готовое поле формы ReCaptchaField и виджет, который сам подтягивает скрипт Google. На момент написания актуальна ветка 4.x; проверьте страницу пакета на PyPI, если ставите позже.
Проверка: pip show django-recaptcha выводит установленную версию без ошибок.
Шаг 2. Регистрируем приложение и ключи
В settings.py добавьте приложение в INSTALLED_APPS и пропишите ключи. Ключи держите не в коде, а в переменных окружения — в примере показаны заглушки.
import os
INSTALLED_APPS = [
# ... остальные приложения
"django_recaptcha",
]
# Ключи из консоли reCAPTCHA. В проде читайте их из окружения.
RECAPTCHA_PUBLIC_KEY = os.environ.get("RECAPTCHA_PUBLIC_KEY", "YOUR_SITE_KEY")
RECAPTCHA_PRIVATE_KEY = os.environ.get("RECAPTCHA_PRIVATE_KEY", "YOUR_SECRET_KEY")Проверка: python manage.py check завершается без ошибок конфигурации.
Шаг 3. Добавляем поля в форму
Создаём форму с обычными полями, капчей и honeypot. Honeypot — скрытое поле, которое человек не видит и не заполняет, а бот заполняет автоматически. Если оно не пустое — это бот.
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="Email")
message = forms.CharField(widget=forms.Textarea, label="Сообщение")
# Ловушка для ботов: люди её не видят, боты заполняют.
website = forms.CharField(required=False, widget=forms.HiddenInput)
captcha = ReCaptchaField(widget=ReCaptchaV2Checkbox)
def clean_website(self):
# Если скрытое поле заполнено — перед нами бот.
if self.cleaned_data.get("website"):
raise forms.ValidationError("Спам не принимается.")
return self.cleaned_data["website"]Проверка: импорт формы в shell (python manage.py shell, затем from myapp.forms import ContactForm) проходит без ImportError.
Шаг 4. View и шаблон
View стандартный. Важно: сохраняйте POST-данные в форму при невалидности, иначе пользователь увидит пустые поля и уйдёт.
from django.shortcuts import render, redirect
from .forms import ContactForm
def contact(request):
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
# Здесь отправка письма или запись в базу
return redirect("contact_done")
else:
form = ContactForm()
return render(request, "contact.html", {"form": form})Шаблон. CSRF-токен обязателен — без него Django вернёт 403 на POST.
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Отправить</button>
</form>Скрытое honeypot-поле website Django отрендерит как <input type="hidden"> автоматически. Скрипт reCAPTCHA виджет подтягивает сам.
Проверка: откройте страницу — под полями появится блок «Я не робот» с галочкой. Если блок не появился, смотрите раздел ниже.
Если не получилось
Четыре ошибки, на которые новички натыкаются чаще всего.
- «ERROR for site owner: Invalid site key» на месте капчи. Публичный ключ не совпадает с ключом из консоли, либо перепутаны местами публичный и секретный. Проверьте, что
RECAPTCHA_PUBLIC_KEY— это именно ключ сайта. - Капча всегда не проходит валидацию, хотя галочку ставите. Секретный ключ неверный или домен в консоли reCAPTCHA не совпадает с тем, откуда открыта форма. Для локалки добавьте
127.0.0.1иlocalhostв список доменов. - 403 Forbidden после отправки. Пропущен
{% csrf_token %}в шаблоне. CSRF-защита в Django включена по умолчанию черезCsrfViewMiddleware— тег обязателен для любой POST-формы, не только с капчей. - Блок капчи не отображается. Чаще всего мешает CSP или блокировщик, который режет домен Google. Откройте консоль браузера: если там ошибка загрузки скрипта reCAPTCHA — дело в блокировке запросов к
google.com/recaptcha.
Частые ошибки новичков
Форма технически работает, но защита дырявая. Вот что упускают.
CSRF-токен и капча решают разные задачи. CSRF защищает от подделки запроса с чужого сайта, капча — от автоматических отправок. Одно не заменяет другое.
Многие ставят капчу и отключают CSRF, думая, что капча «и так всё закрывает». Это ошибка: злоумышленник может подделать межсайтовый запрос от имени залогиненного пользователя, и капча тут ни при чём. Оставляйте CsrfViewMiddleware включённым.
Вторая ошибка — хранить секретный ключ прямо в settings.py и коммитить в репозиторий. Ключ утечёт вместе с историей git. Читайте его из переменной окружения, как в примере выше.
| Механизм | От чего защищает | Виден пользователю |
|---|---|---|
| CSRF-токен | Подделка запроса с чужого сайта | Нет |
| Honeypot | Простые боты, заполняющие все поля | Нет |
| reCAPTCHA v2 | Автоматические массовые отправки | Да, галочка |
Что делать дальше
Форма защищена по базовому минимуму. Дальше по возрастанию усилий: перенесите ключи в .env и подключите чтение через django-environ или os.environ, если ещё этого не сделали. Если галочка reCAPTCHA v2 раздражает пользователей, посмотрите reCAPTCHA v3 — она работает без клика, но требует настройки порога score и логики отклонения, это отдельная тема. Для форм под высокой нагрузкой добавьте ещё и rate limiting по IP — капча снижает поток, но не ограничивает частоту.
Помощник по курсовой и диплому: Большая работа поэтапно: от плана до защиты
Спросить за 25 ₽Источники: Django: CSRF protection (официальная документация), django-recaptcha на PyPI
Частые вопросы
А если у меня Django 4.2, а не 5.x?
Капча появилась, но форма всё равно принимает спам. Почему?
Обязательно ли использовать Google reCAPTCHA?
Грозит ли что-то, если я оставлю секретный ключ в settings.py?
Honeypot достаточно, чтобы не ставить капчу?
Не отображается блок капчи в проде, хотя локально всё работало. Что смотреть?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.