Django База [2023]: Добавление ReCAPTCHA на сайт Django #30
Django

Django База [2023]: Добавление ReCAPTCHA на сайт Django #30

Razilator

В этой статье мы рассмотрим добавление ReCAPTCHA для форм нашего Django проекта, с помощью данного модуля мы обезопасим наш сайт от спама.

Установка ReCAPTCHA

Для работы ReCAPTCHA в Django нам необходимо установить пакет django-recaptcha, делается это следующей командой: pip install django-recaptcha

Результат установки:

Терминал
(venv) PS C:\Users\Razilator\Desktop\Base\backend> pip install django-recaptcha
Collecting django-recaptcha
  Using cached django_recaptcha-3.0.0-py3-none-any.whl (22 kB)
Requirement already satisfied: django in c:\users\razilator\desktop\base\venv\lib\site-packages (from django-recaptcha) (4.1.5)
Requirement already satisfied: asgiref<4,>=3.5.2 in c:\users\razilator\desktop\base\venv\lib\site-packages (from django->django-recaptcha) (3.6.0)
Requirement already satisfied: sqlparse>=0.2.2 in c:\users\razilator\desktop\base\venv\lib\site-packages (from django->django-recaptcha) (0.4.3)
Requirement already satisfied: tzdata in c:\users\razilator\desktop\base\venv\lib\site-packages (from django->django-recaptcha) (2022.7)
Installing collected packages: django-recaptcha
Successfully installed django-recaptcha-3.0.0

[notice] A new release of pip available: 22.3 -> 23.0
[notice] To update, run: python.exe -m pip install --upgrade pip

Отлично, далее нам необходимо добавить модуль captcha в конфигурационный файл Django, а именно в INSTALLED_APPS:

backend/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sites',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'modules.blog.apps.BlogConfig',
    'modules.system.apps.SystemConfig',
    'mptt',
    'debug_toolbar',
    'taggit',
    'captcha',
]

Получение ключей для ReCAPTCHA

Теперь нам следует получить ключ для РеКапчи, для этого нам необходимо зарегистрировать свой сайт здесь: google.com/recaptcha/

Далее по скриншотам:

Нажимаем на кнопку создать
Нажимаем на кнопку создать

Лично я выбрал ReCAPTCHA v2, по желанию вы можете ставить v3 и соответственно настраивать ReCAPTCHA третей версии из документации к модулю.

Заполняем свой домен, но если вы ещё не используете VDS и у вас нет домена и вы хотите протестировать капчу на локальном компьютере, то вписывайте localhost и 127.0.0.1

Заполненные данные в форме
Заполненные данные в форме
И при отправке, я получаю следующие ключи
И при отправке, я получаю следующие ключи

Добавление ключей в конфигурационный файл

После получения ключей нам необходимо их добавить в settings.py нашего проекта, в самый низ добавлю следующие строки:

backend/settings.py
RECAPTCHA_PUBLIC_KEY = '6Lc3Z1AhAAAAACf7fNueWxIXWjH117-wgbXGyykB'
RECAPTCHA_PRIVATE_KEY = '6Lc3Z1AhAAAAAAOjLoGOWA_kljXQaYO2CXGDt0ro'

Обновление существующих форм

Ну и наконец переходим к обновлению наших форм для работы ReCAPTCHA, для этого открываем файл forms.py нашего приложения system, и редактируем формы, добавив капчу к трем формам, вы можете добавить капчу к любой необходимой форме.

system/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, PasswordResetForm
from django.contrib.auth.models import User
from django.conf import settings
from captcha.fields import ReCaptchaField
from captcha.widgets import ReCaptchaV2Checkbox


class UserRegisterForm(UserCreationForm):
    """
    Переопределенная форма регистрации пользователей
    """

    class Meta(UserCreationForm.Meta):
        fields = UserCreationForm.Meta.fields + ('email', 'first_name', 'last_name')

    recaptcha = ReCaptchaField(widget=ReCaptchaV2Checkbox, public_key=settings.RECAPTCHA_PUBLIC_KEY,
                               private_key=settings.RECAPTCHA_PRIVATE_KEY, label='ReCAPTCHA')

    def clean_email(self):
        """
        Проверка email на уникальность
        """
        email = self.cleaned_data.get('email')
        username = self.cleaned_data.get('username')
        if email and User.objects.filter(email=email).exclude(username=username).exists():
            raise forms.ValidationError('Такой email уже используется в системе')
        return email

    def __init__(self, *args, **kwargs):
        """
        Обновление стилей формы регистрации
        """
        super().__init__(*args, **kwargs)
        for field in self.fields:
            self.fields['username'].widget.attrs.update({"placeholder": 'Придумайте свой логин'})
            self.fields['email'].widget.attrs.update({"placeholder": 'Введите свой email'})
            self.fields['first_name'].widget.attrs.update({"placeholder": 'Ваше имя'})
            self.fields["last_name"].widget.attrs.update({"placeholder": 'Ваша фамилия'})
            self.fields['password1'].widget.attrs.update({"placeholder": 'Придумайте свой пароль'})
            self.fields['password2'].widget.attrs.update({"placeholder": 'Повторите придуманный пароль'})
            self.fields[field].widget.attrs.update({"class": "form-control", "autocomplete": "off"})


class UserLoginForm(AuthenticationForm):
    """
    Форма авторизации на сайте
    """

    recaptcha = ReCaptchaField(widget=ReCaptchaV2Checkbox, public_key=settings.RECAPTCHA_PUBLIC_KEY,
                               private_key=settings.RECAPTCHA_PRIVATE_KEY, label='ReCAPTCHA')

    def __init__(self, *args, **kwargs):
        """
        Обновление стилей формы регистрации
        """
        super().__init__(*args, **kwargs)
        for field in self.fields:
            self.fields['username'].widget.attrs['placeholder'] = 'Логин пользователя'
            self.fields['password'].widget.attrs['placeholder'] = 'Пароль пользователя'
            self.fields['username'].label = 'Логин'
            self.fields[field].widget.attrs.update({
                'class': 'form-control',
                'autocomplete': 'off'
            })


class UserForgotPasswordForm(PasswordResetForm):
    """
    Запрос на восстановление пароля
    """

    recaptcha = ReCaptchaField(widget=ReCaptchaV2Checkbox, public_key=settings.RECAPTCHA_PUBLIC_KEY,
                               private_key=settings.RECAPTCHA_PRIVATE_KEY, label='ReCAPTCHA')

    def __init__(self, *args, **kwargs):
        """
        Обновление стилей формы
        """
        super().__init__(*args, **kwargs)
        for field in self.fields:
            self.fields[field].widget.attrs.update({
                'class': 'form-control',
                'autocomplete': 'off'
            })

Таким образом мы установили капчу на регистрацию, авторизацию, а также на запрос о смене пароля.

Проверка в работе

Теперь давайте проверим как это все выглядит на нашем сайте:

При авторизации теперь появилась проверка
При авторизации теперь появилась проверка
Успешно проверяемся, значит все работает
Успешно проверяемся, значит все работает
Капча в форме регистрации
Капча в форме регистрации
При запросе нового пароля
При запросе нового пароля

И как мы удостоверились по скриншотам, у нас все работает так, как нам необходимо.

;