I\'m using the django-simple-captcha app for my django based website, I am able to integrate the captcha form field into my form, but the problem is, how do I create a butto
Here's a working implementation in javascript:
$(function() {
// Add refresh button after field (this can be done in the template as well)
$('img.captcha').after(
$('<a href="#void" class="captcha-refresh">Refresh</a>')
);
// Click-handler for the refresh-link
$('.captcha-refresh').click(function(){
var $form = $(this).parents('form');
var url = location.protocol + "//" + window.location.hostname + ":"
+ location.port + "/captcha/refresh/";
// Make the AJAX-call
$.getJSON(url, {}, function(json) {
$form.find('input[name="captcha_0"]').val(json.key);
$form.find('img.captcha').attr('src', json.image_url);
});
return false;
});
});
Then you just need to add some CSS for the class captcha-refresh
, perhaps place an image in the <a>
and you're good to go!
The chosen answer is with jQuery not JavaScript.
If using purely JavaScript you should do this instead. This will also refresh the audio not just the image django-simple-captcha uses.
https://django-simple-captcha.readthedocs.io/en/latest/advanced.html#rendering
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
custom_field.html:
{% load i18n %}
{% spaceless %}
<label class="control-label">{{ label }}</label>
<img src="{{ image }}" alt="captcha" class="captcha" />
<br/>
<audio id="audio" controls>
<source id="audioSource" src="{{ audio }}" />
</audio>
{% include "django/forms/widgets/multiwidget.html" %}
{% endspaceless %}
Forms.py:
class CustomCaptchaTextInput(CaptchaTextInput):
template_name = 'custom_field.html'
class Form(forms.Form):
captcha = CaptchaField(widget=CustomCaptchaTextInput)
def __init__(self, *args, **kwargs):
super(Form, self).__init__(*args, **kwargs)
self.fields['captcha'].widget.attrs['placeholder'] = 'Solve the captcha'
self.fields['captcha'].label = "Captcha"
Add this at the end of the body tag:
<script>
const captchas = document.querySelectorAll('img.captcha')
function headers(options) {
options = options || {}
options.headers = options.headers || {}
options.headers['X-Requested-With'] = 'XMLHttpRequest'
return options
}
for (const captcha of captchas) {
const anchor = document.createElement('a')
anchor.href = '#void'
anchor.classList.add('captcha-refresh')
anchor.textContent = 'Refresh'
anchor.addEventListener('click', ({ target }) => {
const url = `${window.location.origin}/captcha/refresh/`
let formEl = target.parentElement
while (formEl && formEl.tagName.toLowerCase() !== 'form') {
formEl = formEl.parentElement
}
fetch(url, headers())
.then(res => res.json())
.then(json => {
formEl.querySelector('input[name="captcha_0"]').value = json.key
captcha.setAttribute('src', json.image_url)
document.getElementById('audioSource').setAttribute('src', json.audio_url)
document.getElementById('audio').load()
})
.catch(console.error)
return false
})
captcha.after(anchor)
}
</script>