8

Is there any solutions to use captcha with django-allauth? I want to use captcha on registration form for standard email+password registrations.

Antonio
  • 822
  • 1
  • 10
  • 19

4 Answers4

31

I too needed to do this with django-allauth and found that implementing the django-recaptcha package to be relatively simple.

Configure django-recaptcha

Sign up for a recaptcha account.

Plug your settings in

# settings.py

RECAPTCHA_PUBLIC_KEY = 'xyz'
RECAPTCHA_PRIVATE_KEY = 'xyz'

RECAPTCHA_USE_SSL = True     # Defaults to False

Customize SignupForm

After installing django-recaptcha, I followed someguidelines for customizing the SignupForm.

from django import forms
from captcha.fields import ReCaptchaField

class AllAuthSignupForm(forms.Form):

    captcha = ReCaptchaField()

    def save(self, request, user):
        user = super(AllAuthSignupForm, self).save(request)
        return user

You also need to tell allauth to inherit from this form in settings.py

ACCOUNT_SIGNUP_FORM_CLASS = 'myapp.forms.AllAuthSignupForm'

Wire up signup form template

{{ form.captcha }} and {{ form.captcha.errors }} should be available on the signup template context at this point.

That was it! Seems like all the validation logic is tucked into the ReCaptchaField.

dangel
  • 7,238
  • 7
  • 48
  • 74
scvnc
  • 980
  • 1
  • 9
  • 9
  • 1
    I have tried with latest version of django-allauth and it doesn't required template changes. Just add new captcha field in model and that's it. – webbyfox Mar 28 '17 at 15:11
  • That's brilliant. Is there any way the captcha field can be added at the very end. I am using django-allauth app. – Prithviraj Mitra Aug 08 '17 at 16:58
  • @PrithvirajMitra did u manage to get the captcha field at the very end? I'm having the same problem. – Zorgan Apr 02 '18 at 08:24
  • @Zorgan No (Using django-allauth). So I had to use django-recaptcha package and then inside signupform in forms.py, I put `captcha = ReCaptchaField(attrs={'theme' : 'clean'})`. Before that I had to import `from captcha.fields import ReCaptchaField` . – Prithviraj Mitra Apr 03 '18 at 08:04
  • the django-recaptcha doesn't allow the captcha to be optional, so I rolled my own solution for server side captcha https://github.com/praekelt/django-recaptcha/issues/217 – Harry Moreno May 24 '20 at 18:35
  • I think the edits to this post might be incorrect... see https://bhoey.com/blog/integrating-recaptcha-with-django-allauth/ which is identical to the original post, and does work as of October 2020 – dangel Oct 08 '20 at 00:34
3

To get the ReCaptcha field to the bottom of the form, simply add the other fields before the captcha field. So what was user, email, captcha, password1, password2 becomes user, email, password1, password2, captcha with this form:

from allauth.account.forms import SignupForm, PasswordField
from django.utils.translation import ugettext_lazy as _
from captcha.fields import ReCaptchaField

class UpdatedSignUpForm(SignupForm):
    password1 = PasswordField(label=_("Password"))
    password2 = PasswordField(label=_("Password (again)"))
    captcha = ReCaptchaField()

    def save(self, request):
        user = super(UpdatedSignUpForm, self).save(request)
        return user

You then just need to add this form into the settings.py file as described in the previous answer.

Teri Forey
  • 49
  • 3
1

You can also take a look at Form.field_order.

So a simple sign up form using django-allauth, with captcha and the fields ordered as you wish, would look like this:

from allauth.account.forms import SignupForm
from captcha.fields import ReCaptchaField


class MyCustomSignupForm(SignupForm):
    captcha = ReCaptchaField()

    field_order = ['email', 'password1', 'captcha']

In this case, the captcha will be at the very end.

Jorge Alvarado
  • 372
  • 2
  • 12
1

The accepted answer is mostly fine, but produced this error for me when submitting the sign up form:

save() missing 1 required positional argument: 'user'

To fix this, your custom form could look like this

class AllAuthSignupForm(forms.Form):

    captcha = ReCaptchaField()

    def signup(self, request, user):
        pass

NOTE: django-allauth also warns if the custom signup form does not have signup method.