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 <pinkeen@gmail.com>
- 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
|
Comments
Uups, the first line in ReCaptchaWidget.render is not needed.
#
^ Fixed
#