A very simple, yet powerful, Django captcha application for adding CAPTCHA image challenges to forms
—
Django Simple Captcha provides seamless integration with Django forms through dedicated form fields and widgets. The CaptchaField automatically handles validation while the widget system manages the visual presentation and user interaction.
Main form field class that provides automatic captcha validation as part of Django's form processing pipeline.
class CaptchaField(MultiValueField):
def __init__(*args, **kwargs):
"""
Initialize captcha field.
Parameters:
- widget: CaptchaTextInput instance (optional)
- id_prefix: str, prefix for HTML element IDs (optional)
- generator: str/callable, challenge generator function (optional)
"""
def compress(data_list):
"""
Join field values with comma separator.
Parameters:
- data_list: list, form field values
Returns:
str: Comma-separated values
"""
def clean(value):
"""
Validate captcha response against stored challenge.
Parameters:
- value: str, user-submitted captcha response
Returns:
str: Validated response
Raises:
ValidationError: If captcha response is invalid or expired
"""Primary widget for rendering captcha with image, input field, and optional refresh functionality.
class CaptchaTextInput(BaseCaptchaTextInput):
def __init__(attrs=None, id_prefix=None, generator=None):
"""
Initialize captcha widget.
Parameters:
- attrs: dict, HTML attributes for widget (optional)
- id_prefix: str, prefix for HTML element IDs (optional)
- generator: str/callable, challenge generator function (optional)
"""
def render(name, value, attrs=None, renderer=None):
"""
Render complete captcha widget HTML.
Parameters:
- name: str, field name
- value: str, current field value
- attrs: dict, HTML attributes (optional)
- renderer: renderer instance (optional)
Returns:
str: Rendered HTML for captcha widget
"""
def get_context(name, value, attrs):
"""
Build context variables for template rendering.
Parameters:
- name: str, field name
- value: str, current field value
- attrs: dict, HTML attributes
Returns:
dict: Template context with image_url, audio_url, refresh_url, etc.
"""Supporting widget classes for specific input elements within the captcha widget.
class CaptchaHiddenInput(HiddenInput):
def build_attrs():
"""
Add autocomplete=off attribute to hidden input.
Returns:
dict: HTML attributes with autocomplete disabled
"""
class CaptchaAnswerInput(TextInput):
def build_attrs():
"""
Disable browser assistance features for captcha input.
Returns:
dict: HTML attributes with autocorrect, autocomplete, spellcheck disabled
"""Core widget functionality shared across captcha widget implementations.
class BaseCaptchaTextInput(MultiWidget):
def fetch_captcha_store(name, value, attrs=None, generator=None):
"""
Create new captcha challenge and return store instance.
Parameters:
- name: str, field name
- value: str, current field value
- attrs: dict, HTML attributes (optional)
- generator: str/callable, challenge generator (optional)
Returns:
CaptchaStore: New captcha instance
"""
def image_url():
"""
Get URL for captcha image.
Returns:
str: Image URL path
"""
def audio_url():
"""
Get URL for captcha audio file.
Returns:
str: Audio URL path
"""
def refresh_url():
"""
Get URL for AJAX captcha refresh.
Returns:
str: Refresh endpoint URL
"""
def decompress(value):
"""
Split comma-separated captcha value into components.
Parameters:
- value: str, comma-separated captcha value
Returns:
list: Split components [hashkey, response]
"""
def id_for_label(id_):
"""
Generate proper label ID for accessibility.
Parameters:
- id_: str, base element ID
Returns:
str: Label-compatible ID
"""from django import forms
from captcha.fields import CaptchaField
class CommentForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
comment = forms.CharField(widget=forms.Textarea)
captcha = CaptchaField()from captcha.fields import CaptchaField, CaptchaTextInput
class RegistrationForm(forms.Form):
username = forms.CharField(max_length=30)
password = forms.CharField(widget=forms.PasswordInput)
# Custom captcha widget with specific generator
captcha = CaptchaField(
widget=CaptchaTextInput(
attrs={'class': 'form-control'},
id_prefix='registration',
generator='captcha.helpers.math_challenge'
)
)from django import forms
from django.contrib.auth.models import User
from captcha.fields import CaptchaField
class UserCreationForm(forms.ModelForm):
captcha = CaptchaField()
class Meta:
model = User
fields = ['username', 'email', 'password']Install with Tessl CLI
npx tessl i tessl/pypi-django-simple-captcha