Skip to content
FitMyKBVerify

FitMyKB Verify

Add a CAPTCHA to a Django form

Check the token in the form's clean() method with one requests call, and show the widget with two lines in the template.

Keys

Keep the secret in an environment variable (FMK_SECRET) and pass the site key to the template from settings or a context processor.

The form

clean() reads fmk-captcha-response from the request and asks siteverify. The form is invalid until the check passes.

Python · forms.py
# forms.py
import os
import requests
from django import forms


class SignupForm(forms.Form):
    email = forms.EmailField()

    def __init__(self, *args, request=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean(self):
        token = self.request.POST.get("fmk-captcha-response", "") if self.request else ""
        reply = requests.post("https://fitmykb.com/captcha/siteverify", timeout=5, data={
            "secret": os.environ["FMK_SECRET"], "response": token}).json()
        if not reply.get("success"):
            raise forms.ValidationError("Please complete the check.")
        return super().clean()

The template

Load api.js and place the box inside the form. Pass request to the form in the view so clean() can read the token.

Template and view
{# signup.html #}
<script src="https://fitmykb.com/captcha/api.js" async defer></script>
<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <div class="fmk-captcha" data-sitekey="{{ FMK_SITE_KEY }}"></div>
  <button>Sign up</button>
</form>

# views.py: form = SignupForm(request.POST or None, request=request)

Django REST framework

In a serializer's validate(), read the token from self.context['request'].data and run the same check.

Admin login

To protect /admin/login, use a custom AuthenticationForm with the same clean() and point admin.site.login_form to it.

Get free keys · Full developer docs