This is an example integration of reCAPTCHA v2 into oTree 5.10.3. The implementation includes server-side validation of the user's response and presents a form error if the user did not solve the captcha (correctly).
-
sign up for reCAPTCHA
- select V2 with otherwise default options
- make sure to add
herokuapp.com
as the domain if you intend to use it with Heroku as your hosting provider. - for development, also add
localhost
-
add
requests
to the requirements.txt -
install:
pip install -r requirements.txt
"
Add the credentials to your settings.py
. You get them as part of the sign up process to reCAPTCHA.
# settings.py
RECAPTCHA_SITE_KEY = "MyRecaptchaSiteKey123"
RECAPTCHA_SECRET_KEY = "MyRecaptchaSecretKey456"
Better yet, use environmental variables (on heroku):
# settings.py
RECAPTCHA_SITE_KEY = environ.get('RECAPTCHA_SITE_KEY', '')
RECAPTCHA_SECRET_KEY = environ.get('RECAPTCHA_SECRET_KEY', '')
Add the necessary import statements at the top of your __init__.py
:
# __init__.py
import requests
from otree.settings import RECAPTCHA_SECRET_KEY, RECAPTCHA_SITE_KEY
Add a field to your player model:
# __init__.py
class Player(BasePlayer):
is_human = models.BooleanField(initial=False)
On the page that you want to use reCAPTCHA, add the following code to send the RECAPTCHA_SITE_KEY
to the template, handle captcha validation, and show an error message if needed:
# __init__.py
class MyPage(Page):
def vars_for_template(player: Player):
return {
"RECAPTCHA_SITE_KEY": RECAPTCHA_SITE_KEY
}
def live_method(player: Player, data):
if recaptcha_valid(data["response_token"]):
player.is_human = True
@staticmethod
def error_message(player, values):
if not player.is_human:
return 'You did not solve the captcha.'
Add the referenced recaptcha_valid()
function.
# __init__.py
def recaptcha_valid(response_token):
res = requests.post("https://www.google.com/recaptcha/api/siteverify", data={
'secret': RECAPTCHA_SECRET_KEY,
'response': response_token
})
return res.json()["success"]
On the template for the page, add the following code to the content block
to render the captcha:
<!-- place in content block, where all formfields live -->
<div class="g-recaptcha" data-sitekey="{{ RECAPTCHA_SITE_KEY }}" data-callback="verify_token"></div>
And finally add the following scripts to the same template:
{{ block scripts }}
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script>
function verify_token(response_token) {
liveSend({'response_token': response_token});
}
</script>
{{ endblock }}