Django form field and widget integration for Google reCAPTCHA services, supporting reCAPTCHA V2 and V3.
—
Widget implementations for different reCAPTCHA types, providing various user interaction patterns and security models. All widgets extend the base ReCaptchaBase class and integrate with Django's widget system for form rendering.
Base widget class providing common functionality for all reCAPTCHA widget types. Handles UUID generation, CSS class management, template context building, and data attribute configuration.
class ReCaptchaBase(widgets.Widget):
"""
Base widget for Google reCAPTCHA integration.
Provides common functionality for all reCAPTCHA widget types.
"""
recaptcha_response_name = "g-recaptcha-response"
def __init__(self, api_params=None, *args, **kwargs):
"""
Initialize base reCAPTCHA widget.
Parameters:
- api_params (dict, optional): Additional API parameters for reCAPTCHA
- **kwargs: Standard Django widget parameters
"""
def value_from_datadict(self, data, files, name):
"""
Extract reCAPTCHA response value from form data.
Parameters:
- data (dict): Form data dictionary
- files (dict): Form files dictionary
- name (str): Field name
Returns:
str | None: reCAPTCHA response token or None
"""
def get_context(self, name, value, attrs):
"""
Build template context for widget rendering.
Parameters:
- name (str): Field name
- value: Field value
- attrs (dict): Widget attributes
Returns:
dict: Template context including public_key, widget_uuid, api_params, recaptcha_domain
"""
def build_attrs(self, base_attrs, extra_attrs=None):
"""
Build widget HTML attributes.
Parameters:
- base_attrs (dict): Base attributes
- extra_attrs (dict, optional): Additional attributes
Returns:
dict: Complete widget attributes including data-widget-uuid, data-callback, data-size
"""Standard reCAPTCHA V2 checkbox widget that displays the familiar "I'm not a robot" checkbox interface. Users must click the checkbox and may need to complete additional challenges.
class ReCaptchaV2Checkbox(ReCaptchaBase):
"""
reCAPTCHA V2 Checkbox widget.
Displays standard checkbox interface requiring user interaction.
"""
input_type = "hidden"
template_name = "django_recaptcha/widget_v2_checkbox.html"reCAPTCHA V2 Invisible widget that runs in the background without displaying a visible checkbox. Automatically triggers on form submission and may show challenges for suspicious traffic.
class ReCaptchaV2Invisible(ReCaptchaBase):
"""
reCAPTCHA V2 Invisible widget.
Runs invisibly in background, showing challenges only when needed.
"""
input_type = "hidden"
template_name = "django_recaptcha/widget_v2_invisible.html"
def build_attrs(self, base_attrs, extra_attrs=None):
"""
Build attributes with forced invisible size.
Overrides data-size to "invisible" regardless of input.
"""reCAPTCHA V3 widget that provides score-based validation without user interaction. Analyzes user behavior and returns a score (0.0-1.0) indicating likelihood of being human.
class ReCaptchaV3(ReCaptchaBase):
"""
reCAPTCHA V3 widget with score-based validation.
Provides frictionless experience with risk analysis scoring.
"""
input_type = "hidden"
template_name = "django_recaptcha/widget_v3.html"
def __init__(self, api_params=None, action=None, required_score=None, *args, **kwargs):
"""
Initialize reCAPTCHA V3 widget.
Parameters:
- api_params (dict, optional): Additional API parameters
- action (str, optional): Action name for analytics and validation
- required_score (float, optional): Minimum required score (0.0-1.0).
Defaults to RECAPTCHA_REQUIRED_SCORE setting.
- **kwargs: Standard widget parameters
"""
def value_from_datadict(self, data, files, name):
"""
Extract V3 response token from form data.
Uses field name instead of standard g-recaptcha-response.
"""
def get_context(self, name, value, attrs):
"""
Build template context including action parameter.
Returns:
dict: Context with action added for V3 template rendering
"""All widgets accept api_params dictionary for additional reCAPTCHA configuration:
widget = ReCaptchaV2Checkbox(api_params={
'hl': 'es', # Language
'theme': 'dark', # Theme
'size': 'compact' # Size
})Widgets support customization through HTML data attributes:
data-callback: JavaScript callback function namedata-size: Widget size ('normal', 'compact', 'invisible')data-theme: Color theme ('light', 'dark')data-sitekey: Automatically set to public keyEach widget uses Django templates that can be overridden:
django_recaptcha/widget_v2_checkbox.htmldjango_recaptcha/widget_v2_invisible.htmldjango_recaptcha/widget_v3.htmlfrom django import forms
from django_recaptcha.fields import ReCaptchaField
from django_recaptcha.widgets import ReCaptchaV2Checkbox
class MyForm(forms.Form):
captcha = ReCaptchaField(widget=ReCaptchaV2Checkbox())from django_recaptcha.widgets import ReCaptchaV2Invisible
class ContactForm(forms.Form):
name = forms.CharField()
email = forms.EmailField()
captcha = ReCaptchaField(widget=ReCaptchaV2Invisible())from django_recaptcha.widgets import ReCaptchaV3
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
captcha = ReCaptchaField(
widget=ReCaptchaV3(
action='login',
required_score=0.7
)
)class StyledForm(forms.Form):
captcha = ReCaptchaField(
widget=ReCaptchaV2Checkbox(
api_params={'theme': 'dark', 'size': 'compact'},
attrs={
'data-callback': 'onCaptchaSuccess',
'class': 'custom-recaptcha'
}
)
)class MultiLangForm(forms.Form):
captcha = ReCaptchaField(
widget=ReCaptchaV2Checkbox(
api_params={'hl': 'fr'} # French language
)
)Install with Tessl CLI
npx tessl i tessl/pypi-django-recaptcha