mbi/django-simple-captcha

Customize CaptchaField Widget

Pyvonix opened this issue · 1 comments

Technical info:
Python 3.7
Django 2.1.4

Context:
I tried a first approach by following the information of your documentation (and that of django of course).

from captcha.fields import CaptchaField, CaptchaTextInput

captcha = CaptchaField(widget=CaptchaTextInput(attrs={'class': 'form-control'}))

But looking in the rendering of the template, the value of the class is never applied.

Product HTML code:

<div class="field-captcha">
   
  <img src="/captcha/image/e2e00e273cd53c930c22728f2495d2a415c8671b/" alt="captcha" class="captcha"> 
  <input id="id_captcha_0" name="captcha_0" type="hidden" value="e2e00e273cd53c930c22728f2495d2a415c8671b">
  <input autocapitalize="off" autocomplete="off" autocorrect="off" spellcheck="false" id="id_captcha_1" name="captcha_1" type="text">

</div>

So I tried a much more complete approach but as reported in your documentation it is only specified that CaptchaTextInput can be modified. Off it would be more interesting to allow the users to be able to modify the complete rendering of widget. A bit like this:

File app/widget.py:

from captcha.fields import CaptchaField

class CustomCaptchaField(CaptchaField):
    template_name = "custom_path/captcha.html"

File app/forms.py:

from app.widget import CustomCaptchaField

class form(forms.Form):
    captcha = CustomCaptchaField(widget=CaptchaTextInput(attrs={'class': 'form-control'}))

File custom_path/captcha.html:

{% load i18n %}
{% spaceless %}
<div class="form-group">
  <label class="control-label">{{ label }}</label>
  <div class="form-group">
    <div class="input-group mb-3">
      <div class="input-group-prepend">
        {% if audio %}
            <a title="{% trans "Play CAPTCHA as audio file" %}" href="{{ audio }}">
        {% endif %}
        <img src="{{ image }}" alt="captcha" class="captcha" />
      </div>
      {% include "django/forms/widgets/multiwidget.html" %}
    </div>
  </div>
</div>
{% endspaceless %}

Or if it's possible is need more documentation.

mbi commented

The solution is, as you mentioned, to extend CaptchaTextInput (the widget, not the field!) with a custom template. I added an example in 3c6b3d6.

https://django-simple-captcha.readthedocs.io/en/latest/advanced.html#rendering