''' Semi-Portable recaptcha integration with django forms Contact: Filip Sobalski - Add two variables to your app settings, **RECAPTCHA_PUBKEY** and **RECAPTCHA_PRIVKEY** - Derive forms you want to have a captcha from the provided ReCaptchaForm class (how to get it working with ModelForm? any ideas?) - * If you override the form's clean method make sure you firstly call the ReCaptchaForm's clean method * - In your view, upon receiving the form data initialize the form object like this: form = YouCaptchaFormClass(remoteip=request.META['REMOTE_ADDR'], data=request.POST) (or request.GET of course) - this is because reCaptcha needs the user's remote ip. ''' from django import forms from django.utils.safestring import mark_safe import settings import urllib import urllib2 class DummyWidget(forms.Widget): is_hidden = True def render(self, name, value, attrs=None): return '' class DummyField(forms.Field): widget = DummyWidget def clean(self, value): return value class ReCaptchaWidget(forms.TextInput): def get_recaptcha_widget_html(self, field_name): ''' Template for this probably would be an overkill ''' widget = u'' widget += u'
' % field_name widget += u'' widget += u'' return widget def render(self, name, value, attrs=None): return mark_safe(self.get_recaptcha_widget_html(name)) class ReCaptchaResponseField(forms.Field): widget = ReCaptchaWidget class ReCaptchaForm(forms.Form): recaptcha_response_field = ReCaptchaResponseField(label='Prove you are human') recaptcha_challenge_field = DummyField() def __init__(self, remoteip=None, *args, **kwargs): super(ReCaptchaForm, self).__init__(*args, **kwargs) self.remoteip = remoteip ''' This is a trick that makes the captcha the last field ''' response_field = self.fields.pop('recaptcha_response_field') self.fields.insert(len(self.fields), 'recaptcha_response_field', response_field) def clean(self): cleaned_data = self.cleaned_data challenge = cleaned_data.get('recaptcha_challenge_field') response = cleaned_data.get('recaptcha_response_field') if challenge and response: result = self.verify_captcha(challenge, response) if not result: self._errors['recaptcha_response_field'] = self.error_class([u'Incorrect answer, try again.']) del cleaned_data['recaptcha_response_field'] return cleaned_data def verify_captcha(self, challenge, response): url = 'http://www.google.com/recaptcha/api/verify' values = { 'privatekey': settings.RECAPTCHA_PRIVKEY, 'remoteip' : self.remoteip, 'challenge' : challenge, 'response' : response } vrequest = urllib2.Request(url, urllib.urlencode(values)) vresponse = urllib2.urlopen(vrequest) result = vresponse.read().split('\n') if result[0] == 'true': return True return False