Google’s reCAPTCHA is a very popular solution to protect your application or website against bots and spam. It is fairly simple to implement. In this tutorial you will find how to build a form with reCAPTCHA and send request to reCAPTCHA server.
First, register your application in the reCAPTCHA admin.
After registering your website, you will be handed a Client key and a Server key. The Client key will be used in the reCAPTCHA widget which is rendered within the page where you want to place it. The Server key will be stored safely in the server, made available through the settings.py module.
Let’s say we want to add a reCAPTCHA in a comment section of a website. Inside the form you are currently using to post the data, add the following snippet:
{% extends 'base.html' %} {% block content %} <form method="post"> {% csrf_token %} {{ form.as_p }} <script src='https://www.google.com/recaptcha/api.js'></script> <div class="g-recaptcha" data-sitekey="{{RECAPTCHA_CLIENT_KEY}}"></div> <button type="submit" class="btn btn-primary">Submit</button> </form> {% endblock %}
Or, if you use crispy-forms build like in the following snippet.
from crispy_forms.helper import FormHelper from crispy_forms.layout import Submit, Layout, ButtonHolder, HTML, Fieldset class CommentForm(forms.ModelForm): name = forms.CharField(label='Name', error_messages={'required': 'Please, input your name'}) message = forms.CharField(label='Message', widget=forms.Textarea, error_messages={'required': 'Please, input your message'}) class Meta: model = Message def __init__(self, *args, **kwargs): super(CommentForm, self).__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_id = 'comment_form' self.helper.form_class = 'form' self.helper.form_method = 'post' self.helper.form_action = 'comment:index' self.helper.layout = Layout( Fieldset( '', 'name', 'message' ), HTML('<div class="form-group"><div class="g-recaptcha" data-sitekey="' + settings.RECAPTCHA_CLIENT_KEY + '"></div></div>'), ButtonHolder( Submit('submit', 'Send') ) ) self.fields['message'].widget.attrs = {'rows': 3}
Next step is to actually validate the data. It is done by making a POST request to the endpoint https://www.google.com/recaptcha/api/siteverify, containing your Server key and the data from the reCAPTCHA widget, which is identified by g-recaptcha-response. For request I'm going to use the requests
library:
pip install requests
Then you can make the POST in a relatively easier way:
import requests from django.views.generic.edit import FormView from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger class CommentFormView(FormView): form_class = CommentForm success_url = reverse_lazy('comment:thanks') template_name = "comment/index.html" def get_context_data(self, **kwargs): context = super(CommentFormView, self).get_context_data(**kwargs) messages = Message.visible.all() paginator = Paginator(messages, 10) page = self.request.GET.get('page') try: messages = paginator.page(page) except PageNotAnInteger: messages = paginator.page(1) except EmptyPage: messages = paginator.page(paginator.num_pages) context['messages'] = messages return context def form_valid(self, form): recaptcha_response = self.request.POST.get('g-recaptcha-response') data = { 'secret': settings.RECAPTCHA_SERVER_KEY, 'response': recaptcha_response } # without ssl certificat check r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data, verify=False) # with ssl certificat check # r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data) result = r.json() if result['success']: form.save() else: return redirect(reverse('comment:error')) return redirect(self.get_success_url())
Also, you can use ready integration with field and widget like django-recaptcha.