A very simple, yet powerful, Django captcha application for adding CAPTCHA image challenges to forms
—
Django Simple Captcha uses a database-backed storage system for managing captcha challenges and responses. The CaptchaStore model handles challenge generation, expiration management, and validation, while standalone validation functions provide programmatic access to captcha verification.
Core database model that stores captcha challenges, expected responses, and manages expiration lifecycle.
class CaptchaStore(models.Model):
challenge = models.CharField(max_length=32)
response = models.CharField(max_length=32)
hashkey = models.CharField(max_length=40, unique=True)
expiration = models.DateTimeField()
def save(*args, **kwargs):
"""
Auto-generate hashkey and expiration timestamp on save.
Parameters:
- args: positional arguments passed to parent save()
- kwargs: keyword arguments passed to parent save()
"""
def __str__():
"""
String representation of captcha.
Returns:
str: Challenge text
"""
@classmethod
def remove_expired():
"""
Delete expired captcha records from database.
Returns:
None
"""
@classmethod
def generate_key(generator=None):
"""
Create new captcha challenge and store in database.
Parameters:
- generator: str/callable, challenge generator function (optional)
Returns:
str: Generated hashkey for the new captcha
"""
@classmethod
def pick():
"""
Get captcha from pre-generated pool or create new one.
Returns:
CaptchaStore: Captcha instance from pool or newly generated
"""
@classmethod
def create_pool(count=1000):
"""
Pre-generate pool of captcha challenges for performance.
Parameters:
- count: int, number of captchas to generate (default: 1000)
Returns:
None
"""Direct validation functions for programmatic captcha verification outside of form processing.
def captcha_validate(hashkey, response):
"""
Validate captcha response against stored challenge.
Parameters:
- hashkey: str, unique captcha identifier
- response: str, user-provided captcha response
Raises:
rest_framework.exceptions.ValidationError: If hashkey not found, expired, or response incorrect
"""Utility functions for generating captcha-related URLs in templates and views.
def captcha_image_url(key):
"""
Generate image URL for given captcha key.
Parameters:
- key: str, captcha hashkey
Returns:
str: URL path for captcha image
"""
def captcha_audio_url(key):
"""
Generate audio URL for given captcha key.
Parameters:
- key: str, captcha hashkey
Returns:
str: URL path for captcha audio file
"""from captcha.models import CaptchaStore
# Create new captcha
hashkey = CaptchaStore.generate_key()
captcha = CaptchaStore.objects.get(hashkey=hashkey)
print(f"Challenge: {captcha.challenge}")
print(f"Expected response: {captcha.response}")
# Clean up expired captchas
expired_count = CaptchaStore.remove_expired()
print(f"Removed {expired_count} expired captchas")from captcha.models import CaptchaStore
# Create pool of 500 captchas for better performance
created_count = CaptchaStore.create_pool(count=500)
print(f"Created {created_count} captchas in pool")
# Get captcha from pool (or create new if pool empty)
captcha = CaptchaStore.pick()from captcha.validators import captcha_validate
from rest_framework.exceptions import ValidationError
try:
captcha_validate(hashkey='abc123def456', response='user_answer')
print("Captcha valid!")
except ValidationError as e:
print(f"Captcha validation failed: {e}")from captcha.models import CaptchaStore
# Use specific challenge generator
hashkey = CaptchaStore.generate_key(generator='captcha.helpers.math_challenge')
captcha = CaptchaStore.objects.get(hashkey=hashkey)
print(f"Math challenge: {captcha.challenge}")from captcha.helpers import captcha_image_url, captcha_audio_url
# In a view
def custom_captcha_view(request):
hashkey = CaptchaStore.generate_key()
context = {
'captcha_key': hashkey,
'image_url': captcha_image_url(hashkey),
'audio_url': captcha_audio_url(hashkey),
}
return render(request, 'custom_captcha.html', context)The CaptchaStore model creates a table with the following structure:
create_pool() for high-traffic sites to pre-generate captchasremove_expired() regularly via cron job or management commandhashkey and expiration fields for large deploymentsInstall with Tessl CLI
npx tessl i tessl/pypi-django-simple-captcha