DEV Community


Posted on

Django : ReCaptha Everywhere

In the previous post in this series, I talk about how we can use django-recaptcha to make sure our forms are protected from bot spam submission, however it can be tedious to add them to each form and also does not make it hard to add the recaptcha field if the form are generated by a django package that you had installed previously.

Using the django-honeypot middleware method and knowledge on how django-recaptcha work, I had manage to roll my own middleware that inject the Google Recaptcha field into every page that have a form in a Django weebsite.

1) Start a new django app

We Can first start an django app called G_Recaptha, the name of the app can be anything you want but I'm going with this.

python startapp G_Recaptha
Enter fullscreen mode Exit fullscreen mode

2) G_Recaptha middleware

We now should add a file in G_Recaptha.

in this file, insert the following

import re
from django.utils.safestring import mark_safe
from django.template.loader import render_to_string
from django.conf import settings
from django.utils.encoding import force_str
from .helpers import verify_recaptcha

_POST_FORM_RE = re.compile(
    r'(<form\W[^>]*\bmethod\s*=\s*(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE
_HTML_TYPES = ("text/html", "application/xhtml+xml")

class BaseRecapthaMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        return self.get_response(request)

class RecaptchaRequestMiddleware(BaseRecapthaMiddleware):
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if request.is_ajax():
            return None

        return verify_recaptcha(request)

class RecaptchaResponseMiddleware(BaseRecapthaMiddleware):

    def __call__(self, request):
        response = self.get_response(request)

            content_type = response["Content-Type"].split(";")[0]

        except (KeyError, AttributeError):
            content_type = None

        if content_type in _HTML_TYPES:

            def add_recaptcha_field(match):
                return mark_safe(
                    + render_to_string(
                        {'recaptcha_site_key': settings.RECAPTCHA_PUBLIC_KEY},

            response.content = _POST_FORM_RE.sub(
                add_recaptcha_field, force_str(response.content)

        return response

class RecaptchaMiddleware(

Enter fullscreen mode Exit fullscreen mode

this middleware file is almost the exact copy of django-honeypot that have been customize to insert google recaptcha field into and pages in our website that have a form field in the HTML.

3) G_Recaptha

In the file on line 6 we call for verify_recaptcha from file.

Lets now create a file called file and insert the following lines into the file:

import requests
from django.conf import settings
from django.http import HttpResponseBadRequest
from django.template.loader import render_to_string

def verify_recaptcha(request):
    if request.method == "POST":
        recaptcha_response = request.POST.get('g-recaptcha-response')
        data = {
            'secret': settings.RECAPTCHA_PRIVATE_KEY,
            'response': recaptcha_response
        r =
            '', data=data)
        result = r.json()

        if result['success'] and \
                float(result['score']) > settings.RECAPTCHA_REQUIRED_SCORE:
            return None

        respond = render_to_string(
        return HttpResponseBadRequest(respond)

Enter fullscreen mode Exit fullscreen mode

4) G_Recaptha templates

In file, we force insert a html string into all the pages at line 47. This template is located at


the html for the template are

<script src='{{recaptcha_site_key}}'></script>
    //global grecaptcha
    grecaptcha.ready(function() {
        grecaptcha.execute('{{recaptcha_site_key}}', {action: "form"}).then(function(token) {
        document.getElementById('g-recaptcha-response').value = token;
<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response">
Enter fullscreen mode Exit fullscreen mode

In file we also have a template that responds if the user failed the Google Recaptha test with the template name Recaptcha_error.html located at


the template in its barebone is as follow,

<H1>Google ReCaptha Error </H1>
Enter fullscreen mode Exit fullscreen mode

you may want to change the design as required.

5) G_Recaptcha Settings configurations.

lets now open file and make the following changes as follows

    # Custom Google ReCaptcha

    # Custom Google ReCaptcha

# Custom Google Recaptcha
Enter fullscreen mode Exit fullscreen mode

6)Update .env files

Since we are using python-decouple, we should now update the .env file with the following fields

RECAPTCHA_PRIVATE_KEY = '<public_key>'
RECAPTCHA_REQUIRED_SCORE = <value between 0.00 to 1.00>
Enter fullscreen mode Exit fullscreen mode

7) Testing

the easiest place to test is the admin login page


as you can see, the google recaptcha had been displayed located at the bottom of such form

now we should test if we failed the google recaptcha by setting the RECAPTCHA_REQUIRED_SCORE = 1.00 in the .env file


as you can see I had failed the recaptcha test.

now lower the RECAPTCHA_REQUIRED_SCORE = 1.00 to the value you are comfortable with such as 0.85

you should now be able to login as normal.


We now able to protect all the form in our project with google ReCaptcha. Hopefully this will slowdown or stop any attempt to attack our django webpage.

Top comments (0)