Read time: 2 minutes

Django - Adding CAPTCHA validation to your forms

Recently we implemented a “Forgot your password?” feature in one of our django sites and wanted to protect the mechanism so our users wouldn’t get spammy messages from our servers. As much as we may hate it, forms in our sites usually act as spambots magnets. We need some kind of protection and CAPTCHAs usually do a good job.

There are cool tutorials like this one that can help you integrate django-auth views for password reset in your site. In his post we discuss how to add CAPTCHA protection to this mechanism. Our service of choice is reCAPTCHA because of its security and accessibility (plus their cool book digitalization efforts).

August 2018: Please note that this post was written for an older version of Django. Changes in the code might be necessary to adapt it to the latest versions and best practices.

The first step is registering your site in recaptcha to get a key set, for this you will need a Google account (TIP: You can register localhost).

To connect to ReCAPTCHA from django we used django-recaptcha:

sudo easy_install django-recaptcha

Now we have to add our keys to our settings file. Also, we have to add captcha to our INSTALLED_APPS:

# Captcha -
RECAPTCHA_PUBLIC_KEY = 'your public key here'
RECAPTCHA_PRIVATE_KEY = 'your private key here'


Adding captcha validation to any form is as easy as adding a line of code. In our password reset we used one of django’s built-in forms, but that’s not a big deal since we can just subclass it and add a ReCAPTCHA field:

from django.contrib.auth.forms import PasswordResetForm
from captcha.fields import ReCaptchaField

class PasswordResetReCaptchaForm(PasswordResetForm):
    captcha = ReCaptchaField(attrs={'theme' : 'clean'})

Notice that we added an attribute to tweak ReCAPTCHA’s look. There are a lot of possible customizations nicely explained in the docs.

Finally we we have to tell our view to use our form and not the default one:

url(r'^accounts/password/reset/$', 'django.contrib.auth.views.password_reset',
    name='password_reset', kwargs={
      'post_reset_redirect': '/accounts/password/reset/done/',

Notice that, unless you specify it otherwise, this view will use the admin’s password reset template located in registration/password_reset_form.html. Not a problem given you can create a registration folder in your templates directory and replace these templates with your own.

Now, once you finish you may obtain something like this:

Cool stuff!

Like what you read?

Subscribe to our newsletter and get updates on Deep Learning, NLP, Computer Vision & Python.

No spam, ever. We'll never share your email address and you can opt out at any time.
Comments powered by Disqus

Get in touch

Do you have a project in mind?
We'd love to e-meet you!

Thanks for reaching out!

We'll reply as soon as possible.

And in the meantime?
Check out our blog to see what we're currently working on.