views:

542

answers:

3

I did a recaptcha integration using the following django snippet

settings.py

    RECAPTCHA_PUBLIC_KEY = '<your public key>'
    RECAPTCHA_PRIVATE_KEY = '<your private key>'


#widgets.py

    from django import forms
    from django.utils.safestring import mark_safe
    from django.conf import settings
    from recaptcha import captcha

    class ReCaptcha(forms.widgets.Widget):
 recaptcha_challenge_name = 'recaptcha_challenge_field'
 recaptcha_response_name = 'recaptcha_response_field'

 def render(self, name, value, attrs=None):
     return mark_safe(u'%s' % captcha.displayhtml(settings.RECAPTCHA_PUBLIC_KEY))

 def value_from_datadict(self, data, files, name):
     return [data.get(self.recaptcha_challenge_name, None), 
  data.get(self.recaptcha_response_name, None)]


#fields.py

    from django.conf import settings
    from django import forms
    from django.utils.encoding import smart_unicode
    from django.utils.translation import ugettext_lazy as _

    from marcofucci_utils.widgets import ReCaptcha
    from recaptcha import captcha

    class ReCaptchaField(forms.CharField):
 default_error_messages = {
     'captcha_invalid': _(u'Invalid captcha')
 }

 def __init__(self, *args, **kwargs):
     self.widget = ReCaptcha
     self.required = True
     super(ReCaptchaField, self).__init__(*args, **kwargs)

 def clean(self, values):
     super(ReCaptchaField, self).clean(values[1])
     recaptcha_challenge_value = smart_unicode(values[0])
     recaptcha_response_value = smart_unicode(values[1])
     check_captcha = captcha.submit(recaptcha_challenge_value, 
  recaptcha_response_value, settings.RECAPTCHA_PRIVATE_KEY, {})
     if not check_captcha.is_valid:
  raise forms.util.ValidationError(self.error_messages['captcha_invalid'])
     return values[0]


#forms.py

    class RegistrationForm(forms.Form):
 ...
 recaptcha = marcofucci_fields.ReCaptchaField()
 ...

But I have the forms defined in the django forms wizard and it calls the clean method on the field twice, even if the captcha is included in the last form.

As in the following:

    from registration.forms import RegistrationWizard,RegistrationForm,ProfileForm

    url(r'^register/$',
        RegistrationWizard([RegistrationForm,ProfileForm]),
        name='register_wizard'),

How do I circumvent this situation. What is the need to call the clean on the last form twice?

+1  A: 

If a form is bound, it will allways call clean when renderering (even if you don't call form.is_valid).

Paulo Scardine
A: 

i use this snippet: http://djangosnippets.org/snippets/433/ and work fine for me. Only remember to use {{ html_captcha|safe }}} the snippet that you post is a generic version of this one.

luiscar16
A: 

You might want to consider using this instead: django snippet 1644

Chris Case