Добавление капчи в проект на джанго

В статье будет рассмотрено добавление капчи на основе пакета django-simple-captcha. Установим пакет

pip install django-simple-captcha

В settings.py

INSTALLED_APPS = [
...
    'captcha',

...
]

 Далее, по документации нам нужно выполнить миграцию:

python manage.py migrate

Затем, в корневой список маршрутов добавим строчку:

urlpatterns = [
...
    path('captcha/', include('captcha.urls')),
...
]

 Проверять будем на странице с обратной связью. Вот такая форма. Здесь поля name и emailотключены для зарегистрированных пользователей и заполняются из профиля, и используются поля 

name_hidden и email_hidden, т.к. при отправке на сервер отключенные поля не передаются.

class ContactForm(forms.Form):
    name = forms.CharField(
        label='Имя',
        widget=forms.TextInput(attrs={'class': 'form-input'})
    )
    email = forms.CharField(
        required=False,
        label='E-mail',
        widget=forms.TextInput(attrs={'class': 'form-input'})
    )
    content = forms.CharField(
        label="Сообщение",
        widget=forms.Textarea(attrs={'rows': 3}),
        max_length=3000
    )
    captcha = CaptchaField()

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        super(ContactForm, self).__init__(*args, **kwargs)

        if user and user.is_authenticated:
            self.fields['name'].initial = user.username
            self.fields['name'].widget.attrs['disabled'] = True  # Отключаем поле
            self.fields['name'].required = False
            self.fields['email'].initial = user.email
            self.fields['email'].widget.attrs['disabled'] = True  # Отключаем поле
            self.fields['email'].required = False

            # Добавляем скрытые поля для передачи данных на сервер
            self.fields['name_hidden'] = forms.CharField(
                initial=user.username,
                widget=forms.HiddenInput()
            )
            self.fields['email_hidden'] = forms.EmailField(
                initial=user.email,
                widget=forms.HiddenInput()
            )

И представление формы. 

class ContactView(DataMixin, FormView):
    form_class = ContactForm
    success_url = reverse_lazy('home')
    template_name = "notes/contact.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['page_description'] = 'Обратная связь'
        context['page_description_name'] = 'description'
        return self.get_mixin_context(context, title_page='Обратная связь')

    def form_valid(self, form):
        # Если пользователь аутентифицирован, используем данные из скрытых полей
        if self.request.user.is_authenticated:
            name = form.cleaned_data['name_hidden']
            email = form.cleaned_data['email_hidden']
        else:
            # Получаем данные из формы
            name = form.cleaned_data['name']
            email = form.cleaned_data['email']

        content = form.cleaned_data['content']

        # Формируем тему и текст письма
        subject = f"Новое сообщение от {name}"
        message = f"""
        Имя: {name}
        Email: {email}
        Сообщение:
        {content}
        """
        # Отправляем письмо
        try:
            send_mail(
                subject,  # Тема письма
                message,  # Текст письма
                settings.DEFAULT_FROM_EMAIL,  # От кого (ваш email из настроек)
                [settings.EMAIL_ADMIN],  # Кому (ваш email из настроек)
                fail_silently=False,  # Выводить ошибки, если отправка не удалась
            )
            # Добавляем сообщение об успехе
            messages.success(self.request, 'Ваше сообщение успешно отправлено!')
        except Exception as e:
            # Добавляем сообщение об ошибке
            messages.error(self.request, f'Ошибка при отправке письма: {e}')

        return super().form_valid(form)

    def form_invalid(self, form):
        # Восстанавливаем значения полей name и email из скрытых полей
        if self.request.user.is_authenticated:
            form.data = form.data.copy()  # Делаем копию данных формы
            form.data['name'] = form.data.get('name_hidden', '')
            form.data['email'] = form.data.get('email_hidden', '')
        return super().form_invalid(form)

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

И шаблон

{% block content %}
    <div class="article">
        <h2> {{ page_description }}</h2>

        <form method="post">
            {% csrf_token %}

            <div class="form-error">{{ form.non_field_errors }}</div>

            {% for field in form %}
                {% if not field.is_hidden %}  <!-- Проверяем, не является ли поле скрытым -->
                    <div class="form-field">
                        <label class="form-label" for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }}
                        <div class="form-error">{{ field.errors }}</div>
                    </div>
                {% else %}
                    <div class="hidden-field">{{ field }}</div>
                {% endif %}
            {% endfor %}

            <button type="submit">Отправить</button>
        </form>

    </div>
{% endblock %}

Вот пожалуй и всё.

Категория: Программирование | автор: root

Опубликовано: 13-02-2025 17:13 | Обновлено: 25-02-2025 10:47