🐍🎸 Курс Django: Сложная форма с кастомной капчей
Делаем анкету с различными виджетами, защищаем форму с помощью капчи, автоматически отправляем данные и вложенные файлы на email.
Обзор проекта
Анкета кандидата – форма с выпадающим списком, чекбоксами, радиокнопками, полем для загрузки файла резюме и капчей. Основная функциональность:
- Кастомный рендеринг – все поля анкеты выводятся по отдельности, что представляет собой определенную сложность при обработке выпадающего списка, радиокнопок и чекбоксов.
- Кастомная капча и ее обновление без перезагрузки страницы.
- Автоматическая отправка полученных данных (включая файл резюме) на нужный email.
Модели
Три поля в форме – «Вакансия», «Сертификаты» и «Коммерческий опыт» – имеют список возможных ответов.
1. Сертификатов может быть несколько, или ни одного – для хранения множественных ответов в базе и их вывода в виде чекбоксов принято использовать поле и связь ManyToManyField:
2. Вакансии выводятся в виде раскрывающегося списка. В БД такие записи хранят в виде choices, которые, в свою очередь, определяются с помощью кортежей:
3. Коммерческий опыт предполагает только два варианта ответа – либо он есть, либо его нет. Поэтому для хранения этих choices используется BooleanField:
4. Для загрузки файла резюме используется поле FileField. Django автоматически загружает файлы пользователей в поддиректорию media:
5. Информация, которую возвращает о себе модель Application, будет указана в email'e:
Форма
В форме мы используем все поля модели Application, плюс добавляем поле для капчи (подробнее о капче ниже). Здесь же определяем минимальное и максимальное значение для поля «Возраст», а также используем встроенный валидатор FileExtensionValidator для определения допустимых форматов файла резюме:
В классе Meta определяем тип виджетов и устанавливаем значение по умолчанию empty_label для выпадающего списка. Если такое значение не установить, в верхнем поле списка будет выведен пунктир --------.
Для передачи текста плейсхолдеров, стиля form control и установления высоты текстовых полей переопределяем значения нужных атрибутов:
Метод get_message извлекает данные из только что заполненной формы, а send отсылает информацию (включая файл резюме) на нужный email (подробнее о настройках почтового сервера ниже):
Представления
За валидацию формы, сохранение данных в БД и вызов метода отправки информации на email отвечает представление ApplicationView:
Функция refresh_captcha (совместно со скриптом captcha.js) отвечает за обновление капчи:
Представление SuccessView выводит сообщение об успешном сохранении данных:
Как сделать капчу в Django-приложении
Самые популярные сервисы обработки капчи – Google reCaptcha и hCaptcha. В 2022 году появился сервис Yandex SmartCaptcha. У капчи Яндекса только одно очевидное преимущество – она гарантированно будет работать на российских сайтах. Но, по сравнению с reCaptcha и hCaptcha, настройки SmartCaptcha гораздо сложнее, а пользователей обязательно нужно предупреждать об ее использовании на сайте.
Лучшая альтернатива капче, которая сохраняет и куда-то передает пользовательские данные – автономная капча. Такая капча устанавливается прямо в Django-приложение и не занимается сбором данных – просто предлагает пользователю ввести код с картинки. Самая удобная и гибкая капча для Django – django-simple-captcha.
Установка и кастомизация django-simple-captcha
Модуль устанавливается с помощью команды:
Внешний вид и тип задач капчи можно менять как угодно. Все настройки капчи делаются в settings.py. По умолчанию капча использует параметр CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge' и показывает случайные символы:
При желании можно загружать случайные слова из словаря: CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.word_challenge'
Или предлагать простые задачки с помощью CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge' :
В django-simple-captcha настраивается абсолютно все: количество и цвет символов, интенсивность шума и степень искажения. Вместо текстовой капчи можно выбрать аудио. В нашем проекте используются случайные русскоязычные слова из заранее определенного списка. Необходимые настройки в settings.py выглядят так:
Обновление капчи без перезагрузки страницы
Капча получается забористой – хотя в ней используются только русскоязычные слова, иногда их реально сложно прочитать. Настройки читаемости улучшать не следует – тогда капча не будет представлять никакой сложности для ботов. Но для реальных пользователей можно и нужно предусмотреть возможность обновления капчи без перезагрузки формы. За эту функциональность, помимо уже упомянутого представления refresh_captcha, отвечает скрипт captcha.js, подключаемый в шаблоне base.html, маршрут path('captcha/refresh/', refresh_captcha, name='refresh_captcha')
и кнопка с id="refresh-captcha"
.
Как отправить email из Django-приложения
Для отправки имейлов из Django надо либо установить и настроить собственный почтовый сервер (это довольно сложно), либо воспользоваться любым сторонним сервисом, который предоставляет доступ к SMTP для приложений. Такой доступ предоставляет, например, Яндекс.
Как получить пароль для приложения
Учетные данные обычного пользовательского аккаунта нельзя использовать для отправки имейлов из приложений. Чтобы подключить свое приложение к почтовому серверу, надо получить специальный пароль.
Нажмите на шестеренку и выберите Все настройки:
В настройках нажмите на Почтовые программы, отметьте IMAP:
Перейдите в Пароли приложений, затем в Безопасность:
И в разделе Пароли приложений создайте пароль для почты:
Теперь можно сделать все нужные настройки в settings.py:
- RECIPIENT_ADDRESS = 'admin@gmail.com' – это адрес, на который будут приходить сообщения. Адресов можно указать несколько, в виде списка.
- EMAIL_HOST = 'smtp.yandex.ru'
- EMAIL_PORT = 465
- EMAIL_USE_SSL = True
- DEFAULT_FROM_EMAIL = 'sender@yandex.ru' – адрес, который по умолчанию будет указан в поле "от кого".
- EMAIL_HOST_USER = 'yandex_user@yandex.ru' – адрес, в учетной записи которого вы создали пароль для приложения.
- EMAIL_HOST_PASSWORD = 'yourownpasswordhere' – тот самый пароль приложения.
- EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
Эти настройки используются модулем EmailMessage и методом send в форме ApplicationForm. Письма будут приходить с вложенными резюме:
Шаблоны и рендеринг формы
Приложение использует 3 шаблона:
Кастомный рендеринг формы происходит application.html. Для вывода чекбоксов используется цикл и счетчик forloop.counter, который подсчитывает итерации:
При выводе выпадающего списка используются оба значения из кортежа:
При визуализации радиокнопок первое значение из кортежа используется в качестве value, второе в качестве label:
Подведем итоги
В ходе разработки этого проекта мы научились:
- Кастомизировать и обновлять капчу без перезагрузки страницы.
- Рендерить сложные виджеты с помощью пользовательских HTML/CSS стилей.
- Отправлять данные из Django-формы на имейл – в реальном приложении так можно реализовать подписку на вакансии, новости и т.п.
В следующей статье будем подробно разбирать работу с шаблонами. Весь код для этого проекта – в репозитории.