My previous snippet with captcha wasn't very portable but Marco Fucci figured out the thing that I couldn't - value_from_datadict function. So all credits go to him and his snippet, I adapted it to my needs, maybe you like my version better - it doesn't need any captcha libraries and let's you modify the widget's html easily. Also I added an option to pass remoteip to google api's verify method.
How to use it:
In your settings.py add:
RECAPTCHA_PUBKEY = 'your recaptcha public key' RECAPTCHA_PRIVKEY = 'your recaptcha private key'
After that just import and use ReCaptchaField in your form as you would any other field. That's it.
Important If you want to have peace of mind in case google decided that the remoteip parametr is mandatory then: Derive every form that has the captcha field from ReCaptchaForm and when you create the form object after receiving POST/GET, pass a remoteip parameter like that:
form = YourCaptchaForm(data=request.POST, remoteip=request.META['REMOTE_ADDR'])
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 | '''
ReCaptcha for django forms
All credits go to Marco Fucci, I used his idea here and adapted it to my needs.
Contact: Filip Sobalski <[email protected]>
How to use it:
In your settings.py add:
RECAPTCHA_PUBKEY = 'your recaptcha public key'
RECAPTCHA_PRIVKEY = 'your recaptcha private key'
After that just import and use ReCaptchaField in your form as you would any other field. That's it.
*** Important *** If you want to have peace of mind in case google decided that the remoteip parametr is mandatory then:
Derive every form that has the captcha field from ReCaptchaForm and when you create the form object after receiving POST/GET, pass a remoteip parameter like that:
form = YourCaptchaForm(data=request.POST, remoteip=request.META['REMOTE_ADDR'])
'''
from django import forms
from django.utils.safestring import mark_safe
from django.utils.encoding import smart_unicode
import settings
import urllib
import urllib2
class ReCaptchaWidget(forms.Widget):
def get_recaptcha_widget_html(self, field_name):
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"});' % (settings.RECAPTCHA_PUBKEY, field_name)
widget += u'</script>'
return widget
def value_from_datadict(self, data, files, name):
remoteip = None
if 'REMOTE_ADDR' in data:
remoteip = data.get('REMOTE_ADDR')
return {
'challenge' : data.get('recaptcha_challenge_field', None),
'response' : data.get('recaptcha_response_field', None),
'remoteip' : remoteip
}
def render(self, name, value, attrs=None):
return mark_safe(self.get_recaptcha_widget_html(name))
class ReCaptchaField(forms.Field):
widget = ReCaptchaWidget
required = True
def verify_captcha(self, challenge, response, remoteip):
url = 'http://www.google.com/recaptcha/api/verify'
values = {
'privatekey': settings.RECAPTCHA_PRIVKEY,
'challenge' : challenge,
'response' : response
}
if remoteip:
values['remoteip'] = remoteip
vrequest = urllib2.Request(url, urllib.urlencode(values))
vresponse = urllib2.urlopen(vrequest)
result = vresponse.read().split('\n')
if result[0] == 'true':
return (True, result[1])
return (False, result[1])
def clean(self, value):
super(ReCaptchaField, self).clean(value['response'])
result = self.verify_captcha(value['challenge'], value['response'], value['remoteip'])
if not result[0]:
raise forms.ValidationError('Wrong answer, try again.')
return value['response']
class ReCaptchaForm(forms.Form):
def __init__(self, data=None, remoteip=None, *args, **kwargs):
if data and remoteip:
data = data.copy()
data['REMOTE_ADDR'] = remoteip
super(ReCaptchaForm, self).__init__(data=data, *args, **kwargs)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Hey pinkeen, nice snippet.
Got a question for you though. Have you had any problems with the "recaptcha_challenge_field" and "recaptcha_response_field" inputs not existing in your POST data? It seems that using the javascript api prevents these fields from being added to my post data. When I disable javascript everything works fine... any ideas?
I know you have removed the captcha dependency but... it might be better to use it since captcha's displayhtml() method for rendering provides a noscript version of the field.
django 1.2.5 python 2.7 ^^
#
Nevermind. It turns out the template I was using surrounded the form with a table which caused the fields to not be posted. Moving the form elements to surround the table resolved this issue. ^^
#
Please login first before commenting.