2 years ago

#40301

test-img

4L3XK

How to install Google Recaptcha v3 with Django CMS and Aldryn Forms

I am trying to get ReCaptcha v3 working for an aldryn form in django / djangocms.

Instead of the ReCaptcha riddle all I get is a "Recaptchafieldplugin 1*" on the site:

enter image description here

What am I missing? Am I misunderstanding how this "invisible ReCAPTCHA" should work? Should there not be a captcha riddle to solve?

There is a working sample project running. To get recaptcha up and runnning here is what I did so far. I followed the readme.

  • pip install aldryn-forms-recaptcha-plugin
  • adjusted settings.py accordingly
  • set RECAPTCHA_SCORE_THRESHOLD = 1 for testing (1 = always activate recaptcha)
  • set the recaptcha keys in the .env file
  • python manage.py migrate
  • added <script src="https://www.google.com/recaptcha/api.js"></script> to the bottom of the base.html template

Here is the settings.py:

import os # isort:skip
import environ
env = environ.Env()
env.read_env(env.str('ENV_PATH', 'recaptchatest/.env'))
gettext = lambda s: s
DATA_DIR = os.path.dirname(os.path.dirname(__file__))
"""
Django settings for recaptchatest project.

Generated by 'django-admin startproject' using Django 3.1.14.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '***'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['***']


# Application definition





ROOT_URLCONF = 'recaptchatest.urls'



WSGI_APPLICATION = 'recaptchatest.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases




# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/

LANGUAGE_CODE = 'de'

TIME_ZONE = 'Europe/Berlin'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(DATA_DIR, 'media')
STATIC_ROOT = os.path.join(DATA_DIR, 'static')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'recaptchatest', 'static'),
)
SITE_ID = 1


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'recaptchatest', 'templates'),],
        'OPTIONS': {
            'context_processors': [
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.i18n',
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.template.context_processors.media',
                'django.template.context_processors.csrf',
                'django.template.context_processors.tz',
                'sekizai.context_processors.sekizai',
                'django.template.context_processors.static',
                'cms.context_processors.cms_settings'
            ],
            'loaders': [
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader'
            ],
        },
    },
]


MIDDLEWARE = [
    'cms.middleware.utils.ApphookReloadMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'cms.middleware.user.CurrentUserMiddleware',
    'cms.middleware.page.CurrentPageMiddleware',
    'cms.middleware.toolbar.ToolbarMiddleware',
    'cms.middleware.language.LanguageCookieMiddleware'
]

INSTALLED_APPS = [
    'djangocms_admin_style',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.admin',
    'django.contrib.sites',
    'django.contrib.sitemaps',
    'django.contrib.staticfiles',
    'django.contrib.messages',
    'cms',
    'menus',
    'sekizai',
    'treebeard',
    'djangocms_text_ckeditor',
    'filer',
    'easy_thumbnails',
    'djangocms_bootstrap4',
    'djangocms_bootstrap4.contrib.bootstrap4_alerts',
    'djangocms_bootstrap4.contrib.bootstrap4_badge',
    'djangocms_bootstrap4.contrib.bootstrap4_card',
    'djangocms_bootstrap4.contrib.bootstrap4_carousel',
    'djangocms_bootstrap4.contrib.bootstrap4_collapse',
    'djangocms_bootstrap4.contrib.bootstrap4_content',
    'djangocms_bootstrap4.contrib.bootstrap4_grid',
    'djangocms_bootstrap4.contrib.bootstrap4_jumbotron',
    'djangocms_bootstrap4.contrib.bootstrap4_link',
    'djangocms_bootstrap4.contrib.bootstrap4_listgroup',
    'djangocms_bootstrap4.contrib.bootstrap4_media',
    'djangocms_bootstrap4.contrib.bootstrap4_picture',
    'djangocms_bootstrap4.contrib.bootstrap4_tabs',
    'djangocms_bootstrap4.contrib.bootstrap4_utilities',
    'djangocms_file',
    'djangocms_icon',
    'djangocms_link',
    'djangocms_picture',
    'djangocms_style',
    'djangocms_googlemap',
    'djangocms_video',
    'aldryn_forms_bs4_templates',
    'aldryn_forms_recaptcha_plugin',
    'snowpenguin.django.recaptcha3',
    'absolute',
    'aldryn_forms',
    'aldryn_forms.contrib.email_notifications',
    'emailit',
    'recaptchatest'
]

LANGUAGES = (
    ## Customize this
    ('de', gettext('de')),
)

CMS_LANGUAGES = {
    ## Customize this
    1: [
        {
            'code': 'de',
            'name': gettext('de'),
            'redirect_on_fallback': True,
            'public': True,
            'hide_untranslated': False,
        },
    ],
    'default': {
        'redirect_on_fallback': True,
        'public': True,
        'hide_untranslated': False,
    },
}

CMS_TEMPLATES = (
    ## Customize this
    ('fullwidth.html', 'Fullwidth'),
    ('sidebar_left.html', 'Sidebar Left'),
    ('sidebar_right.html', 'Sidebar Right')
)

X_FRAME_OPTIONS = 'SAMEORIGIN'

CMS_PERMISSION = True

CMS_PLACEHOLDER_CONF = {}

DATABASES = {
    'default': {
        'CONN_MAX_AGE': 0,
        'ENGINE': 'django.db.backends.sqlite3',
        'HOST': 'localhost',
        'NAME': 'project.db',
        'PASSWORD': '',
        'PORT': '',
        'USER': ''
    }
}

THUMBNAIL_PROCESSORS = (
    'easy_thumbnails.processors.colorspace',
    'easy_thumbnails.processors.autocrop',
    'filer.thumbnail_processors.scale_and_crop_with_subject_location',
    'easy_thumbnails.processors.filters'
)

RECAPTCHA_PUBLIC_KEY = env('RECAPTCHA_PUBLIC_KEY')
RECAPTCHA_PRIVATE_KEY = env('RECAPTCHA_PRIVATE_KEY')
# set this to 0 (or 1) to deactivate (or always activate) the captcha protection
RECAPTCHA_SCORE_THRESHOLD = 1
# RECAPTCHA_SCORE_THRESHOLD = 0.85

And here is the base.html template:

{% load static cms_tags menu_tags sekizai_tags %}
<!doctype html>
<html>
    <head>
        <title>{% block title %}This is my new project home page{% endblock title %}</title>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
        {% render_block "css" %}
    </head>
    <body>
        {% cms_toolbar %}
        <div class="container">
            <ul class="nav">
                {% show_menu 0 100 100 100 %}
            </ul>
            {% block content %}{% endblock content %}
        </div>
        <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
        <script src="https://www.google.com/recaptcha/api.js"></script>

        {% render_block "js" %}
    </body>
</html>

And this is the source code of the page displayed / after rendering:

<!doctype html>
<html>
<head>
  <title>test</title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
</head>
<body>
  <div class="container">
    <ul class="nav">
      <li class="child selected">
        <a href="/de/">test</a>
      </li>
    </ul>
    <div class="container">
      <form method="post" id="cms-form" class="cms-form">
        <input type="hidden" name="csrfmiddlewaretoken" value="h6gW4d7yIcEsdWrFYN0nU7ETrFJ2QCaV5dLgFrRklSuUqGPTxNlqNLO5HRXal0ja">
        <fieldset>
          <legend>test</legend>
          <div class="form-group">
            <label for="id_text">
              text<span class="required-star">*</span>
            </label>
            <input type="text" name="text" placeholder="text" class=" form-control" required id="id_text">
          </div>
          <div class="form-check mb-3">
            <input type="checkbox" name="check" class=" form-check-input" required id="id_check">
            <label for="id_check" class="form-check-label">
              check
            </label>
          </div>
          <div class="form-group">
            <label for="id_recaptchafieldplugin_1">
              Recaptchafieldplugin 1<span class="required-star">*</span>
            </label>
            <input type="hidden" class="django-recaptcha-hidden-field" name="g-recaptcha-response">
            <script src='https://www.google.com/recaptcha/api.js?render=6LeV2eYdAAAAAIcoinf3B2_lh2fzucrHEo3T9Vap'></script>
            <script>
              grecaptcha.ready(function() {
                var grecaptcha_execute = function() {
                  grecaptcha.execute('6LeV2eYdAAAAAIcoinf3B2_lh2fzucrHEo3T9Vap', {
                    action: 'homepage'
                  }).then(function(token) {
                    document.querySelectorAll('input.django-recaptcha-hidden-field').forEach(function(value) {
                      value.value = token;
                    });
                    return token;
                  })
                };
                grecaptcha_execute()
                setInterval(grecaptcha_execute, 120000);
              });
            </script>
          </div>
        </fieldset>
        <button type="submit" class="btn btn-primary mt-2">
          test
        </button>
        <input type="hidden" name="language" value="de" id="id_language">
        <input type="hidden" name="form_plugin_id" value="55" id="id_form_plugin_id">
        <input type="hidden" class="django-recaptcha-hidden-field" name="g-recaptcha-response">
        <script src='https://www.google.com/recaptcha/api.js?render=6LeV2eYdAAAAAIcoinf3B2_lh2fzucrHEo3T9Vap'></script>
        <script>
          grecaptcha.ready(function() {
            var grecaptcha_execute = function() {
              grecaptcha.execute('6LeV2eYdAAAAAIcoinf3B2_lh2fzucrHEo3T9Vap', {
                action: 'homepage'
              }).then(function(token) {
                document.querySelectorAll('input.django-recaptcha-hidden-field').forEach(function(value) {
                  value.value = token;
                });
                return token;
              })
            };
            grecaptcha_execute()
            setInterval(grecaptcha_execute, 120000);
          });
        </script>
      </form>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
  <script src="https://www.google.com/recaptcha/api.js"></script>
</body>
</html>

django

forms

django-cms

recaptcha-v3

divio

0 Answers

Your Answer

Accepted video resources