It is not so portable and easy as I wanted it to be because of how django forms work - they don't play well with recaptcha.
To get it to work:
- 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 *
-
If you override the form's clean method make sure you firstly call the
-
In your view, upon receiving the form data initialize the objects like this
form = YouFormClassDerivedFromReCaptchaForm(remoteip=request.META['REMOTE_ADDR'], data=request.POST)
(or request.GET of course) - this is because reCaptcha needs the user's remote ip.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | '''
Semi-Portable recaptcha integration with django forms
Contact: Filip Sobalski <[email protected]>
- 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'<div class="recaptcha_box" id="fdiv_%s"></div>' % field_name
widget += u'<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>'
widget += u'<script type="text/javascript">'
widget += u'Recaptcha.create("%s", "fdiv_%s", {theme: "white", callback: Recaptcha.focus_response_field});' % (settings.RECAPTCHA_PUBKEY, field_name)
widget += u'</script>'
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
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 8 months ago
Comments
Uups, the first line in ReCaptchaWidget.render is not needed.
#
^ Fixed
#
Please login first before commenting.