{"id":20915730,"url":"https://github.com/kbytesys/django-recaptcha2","last_synced_at":"2025-08-10T20:09:57.973Z","repository":{"id":35258319,"uuid":"39518221","full_name":"kbytesys/django-recaptcha2","owner":"kbytesys","description":"Django reCaptcha v2 field/widget","archived":false,"fork":false,"pushed_at":"2022-08-16T10:16:05.000Z","size":82,"stargazers_count":75,"open_issues_count":5,"forks_count":43,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-07-27T10:07:15.512Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kbytesys.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-22T16:50:02.000Z","updated_at":"2025-02-22T19:02:20.000Z","dependencies_parsed_at":"2022-09-16T20:01:41.290Z","dependency_job_id":null,"html_url":"https://github.com/kbytesys/django-recaptcha2","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/kbytesys/django-recaptcha2","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kbytesys%2Fdjango-recaptcha2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kbytesys%2Fdjango-recaptcha2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kbytesys%2Fdjango-recaptcha2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kbytesys%2Fdjango-recaptcha2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kbytesys","download_url":"https://codeload.github.com/kbytesys/django-recaptcha2/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kbytesys%2Fdjango-recaptcha2/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269780617,"owners_count":24474686,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T16:18:05.570Z","updated_at":"2025-08-10T20:09:57.850Z","avatar_url":"https://github.com/kbytesys.png","language":"Python","readme":"# Django reCaptcha v2 [![Build Status](https://travis-ci.org/kbytesys/django-recaptcha2.svg?branch=master)](https://travis-ci.org/kbytesys/django-recaptcha2)\n----\n\nThis integration app implements a recaptcha field for \u003ca href=\"https://developers.google.com/recaptcha/intro\"\u003eGoogle reCaptcha v2\u003c/a\u003e\nwith explicit rendering and multiple recaptcha support. The invisible version of the reCAPTCHA with the automatic render mode\nis now supported, please read the related documentation below.\n\nAre you looking for the Google reCaptcha v3? Take a look to the dedicated repository https://github.com/kbytesys/django-recaptcha3\n\n----\n\n## How to install\n\nInstall the required package from pip (or take the source and install it by yourself):\n\n```bash\npip install django-recaptcha2\n```\n\nThen add django-recaptcha2 to your installed apps:\n\n```python\nINSTALLED_APPS = (\n    ...\n    'snowpenguin.django.recaptcha2',\n    ...\n)\n```\n\nAnd add your reCaptcha private and public key to your django settings.py:\n\n```python\nRECAPTCHA_PRIVATE_KEY = 'your private key'\nRECAPTCHA_PUBLIC_KEY = 'your public key'\n# If you require reCaptcha to be loaded from somewhere other than https://google.com\n# (e.g. to bypass firewall restrictions), you can specify what proxy to use.\n# RECAPTCHA_PROXY_HOST = 'https://recaptcha.net'\n```\n\nIf you have to create the apikey for the domains managed by your django project, you can visit this \u003ca href=\"https://www.google.com/recaptcha/admin\"\u003ewebsite\u003c/a\u003e.\n\n## \"I'm not a robot\" Usage \n### Form and Widget\nYou can simply create a reCaptcha enabled form with the field provided by this app:\n\n```python\nfrom snowpenguin.django.recaptcha2.fields import ReCaptchaField\nfrom snowpenguin.django.recaptcha2.widgets import ReCaptchaWidget\n\nclass ExampleForm(forms.Form):\n    [...]\n    captcha = ReCaptchaField(widget=ReCaptchaWidget())\n    [...]\n```\n\nYou can set the private key on the \"private_key\" argument of the field contructor and you can pass some\nparameters into the widget contructor:\n\n```python\nclass ReCaptchaWidget(Widget):\n    def __init__(self, explicit=False, container_id=None, theme=None, type=None, size=None, tabindex=None,\n                 callback=None, expired_callback=None, attrs={}, *args, **kwargs):\n```\n\nIf you set the explicit boolean to true, you will render this field with explicit render support. This is useful if you\nwant to use multiple forms with reCaptcha in one page. Take a look to template and samples sections for more info.\n\nYou can personalize reCaptcha theme, type, size, tabindex, callback and expired_callback parameters. Look the reCaptcha\n\u003ca href=\"https://developers.google.com/recaptcha/docs/display#config\"\u003edocumentation\u003c/a\u003e if you want to change those values.\nWarning: the app doesn't validate the incoming parameter values.\n\n### Recaptcha \"container id\"\nNow the default container id for the recaptcha is:\n\n* recaptcha-{$fieldname} for the automatic rendering\n* recaptcha-{$fieldname}-{%fiverandomdigits} for the explicit rendering\n\nThis avoids name collisions when you use multiple instances of the recaptcha in different forms, but in the same page\nand with the same field name.\n\n**Note:** you can always override the container id with the \"container_id\" argument in the widget constructor, but take\ncare: nobody will check if the id you provide is already used.\n\n### Templating\nYou can use some template tags to simplify the reCaptcha adoption:\n \n* recaptcha_init: add the script tag for reCaptcha api. You have to put this tag somewhere in your \"head\" element\n* recaptcha_explicit_init: add the script tag for the reCaptcha api with explicit render support. You have to put this\n  tag somewhere above the end of your \"body\" element. If you use this tag, you don't have to use \"recaptcha_init\".\n* recaptcha_explicit_support: this tag add the callback function used by reCaptcha for explicit rendering. This tag also\n  add some funcitions and javascript vars used by the ReCaptchaWidget when it is initialized with explicit=True. You have\n  to put this tag somewhere in your \"head\" element.\n* recaptcha_key: if you want to use reCaptcha manually in your template, you will need the sitekey (a.k.a. public api key).\n  This tag returns a string with the configured public key.\n  \nYou can use the form as usual.\n\n### Force widget language\nYou can disable the language auto-detection in the recaptha2 init tag:\n\n```django\n{% load recaptcha2 %}\n\u003chtml\u003e\n  \u003chead\u003e\n      {% recaptcha_init 'es' %}\n  \u003c/head\u003e\n```\n\nor\n\n```django\n    \u003c/form\u003e\n    {% recaptcha_explicit_init 'es'%}\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nFor language codes take a look to \u003ca href=\"https://developers.google.com/recaptcha/docs/language\"\u003ethis page\u003c/a\u003e.\n\n### Samples\n#### Simple render example\n\nJust create a form with the reCaptcha field and follow this template example:\n\n```django\n{% load recaptcha2 %}\n\u003chtml\u003e\n  \u003chead\u003e\n      {% recaptcha_init %}\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cform action=\"?\" method=\"POST\"\u003e\n      {% csrf_token %}\n      {{ form }}\n      \u003cinput type=\"submit\" value=\"Submit\"\u003e\n    \u003c/form\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n#### Explicit render example\n\nCreate a form with explicit=True and write your template like this:\n\n```django\n{% load recaptcha2 %}\n\u003chtml\u003e\n  \u003chead\u003e\n    {% recaptcha_explicit_support %}\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cform action=\"?\" method=\"POST\"\u003e\n      {% csrf_token %}\n      {{ form }}\n      \u003cinput type=\"submit\" value=\"Submit\"\u003e\n    \u003c/form\u003e\n    {% recaptcha_explicit_init %}\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n#### Multiple render example\n\nYou can render multiple reCaptcha using only forms with explicit=True:\n\n```django\n{% load recaptcha2 %}\n\u003chtml\u003e\n  \u003chead\u003e\n      {% recaptcha_explicit_support %}\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cform action=\"{% url 'form1_post' %}\" method=\"POST\"\u003e\n      {% csrf_token %}\n      {{ form1 }}\n      \u003cinput type=\"submit\" value=\"Submit\"\u003e\n    \u003c/form\u003e\n    \u003cform action=\"{% url 'form2_post' %}\" method=\"POST\"\u003e\n      {% csrf_token %}\n      {{ form2 }}\n      \u003cinput type=\"submit\" value=\"Submit\"\u003e\n    \u003c/form\u003e\n    {% recaptcha_explicit_init %}\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n#### Mix manual render with app support\n\nYou can use the app explicit render support also is you implement reCaptcha in one of your form in the template:\n\n```django\n{% load recaptcha2 %}\n\u003chtml\u003e\n    \u003chead\u003e\n        {% recaptcha_explicit_support %}\n    \u003c/head\u003e\n    \u003cbody\u003e\n        [...]\n        \u003cdiv id='recaptcha'\u003e\u003c/div\u003e\n        \u003cscript\u003e\n            django_recaptcha_callbacks.push(function() {\n                grecaptcha.render('recaptcha', {\n                    'theme': 'dark',\n                    'sitekey': '{% recaptcha_key %}'\n                })\n            });\n        \u003c/script\u003e\n        [...]\n        {% recaptcha_explicit_init %}\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n## \"Invisible\" Usage\nThe implementation and the usage of this kind of binding is simpler and you don't need to use the explicit\nrendering to add multiple instances of the reCAPTCHA.\n\n### Form and Widget\nYou can simply create a reCaptcha enabled form with the field provided by this app:\n\n```python\nfrom snowpenguin.django.recaptcha2.fields import ReCaptchaField\nfrom snowpenguin.django.recaptcha2.widgets import ReCaptchaHiddenInput\n\nclass ExampleForm(forms.Form):\n    [...]\n    captcha = ReCaptchaField(widget=ReCaptchaHiddenInput())\n    [...]\n```\n\nYou can set the private key on the \"private_key\" argument of the field contructor.\n\n### Templating\nYou just need to add the \"recaptcha_init\" tag on the head of your page and to place the invisible reCAPTCHA\nsubmit button inside your form:\n\n```django\n\u003cform id='myform1' action=\"?\" method=\"POST\"\u003e\n      {% csrf_token %}\n      {{ form }}\n      {% recaptcha_invisible_button submit_label='Submit' %}\n\u003c/form\u003e\n```\n\nYou can customize the button with the parameters included in its definition:\n\n```python\ndef recaptcha_invisible_button(public_key=None, submit_label=None, extra_css_classes=None,\n                               form_id=None, custom_callback=None):\n``` \n\nYou can override the reCAPTCHA public key, change the label of the button, apply extra css classes, force\nthe button to submit a form identified by id or provide the name of a custom callback. Please check the samples\nto understand how it works.\n\n### Samples\n#### Simple usage\n\n```django\n{% load recaptcha2 %}\n\u003chtml\u003e\n  \u003chead\u003e\n      {% recaptcha_init %}\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cform action=\"?\" method=\"POST\"\u003e\n      {% csrf_token %}\n      {{ form }}\n      {% recaptcha_invisible_button submit_label='Submit' %}\n    \u003c/form\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n**Note:** The button will looking for the first \"form\" element using che \"Element.closest\" function. IE\ndoesn't support it, so please use a polyfill (for example https://polyfill.io). If you don't want to\nadd extra javascript libraries, please use the form id or a custom callback.\n\n#### Form id\n\n```django\n{% load recaptcha2 %}\n\u003chtml\u003e\n  \u003chead\u003e\n      {% recaptcha_init %}\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cform id='myform' action=\"?\" method=\"POST\"\u003e\n      {% csrf_token %}\n      {{ form }}\n      {% recaptcha_invisible_button submit_label='Submit' form_id='myform' %}\n    \u003c/form\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n#### Custom callback\n\n```django\n{% load recaptcha2 %}\n\u003chtml\u003e\n  \u003chead\u003e\n      {% recaptcha_init %}\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cform id='myform' action=\"?\" method=\"POST\"\u003e\n      {% csrf_token %}\n      {{ form }}\n      {% recaptcha_invisible_button submit_label='Submit' custom_callback='mycallback' %}\n      \u003cscript\u003e\n          function mycallback(token) {\n              someFunction();\n              document.getElementById(\"myform\").submit();\n          }\n      \u003c/script\u003e\n    \u003c/form\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n### TODO/ISSUES\n\n- Only the automatic binding is supported, but you can add the dummy widget inside your form and the required\njavascript code in your template in order to use the programmatically bind and invoke.\n\n- You can only configure one reCAPTCHA key in the configuration. This isn't a real problem because if you want \nto use the invisible reCAPTCHA you don't need to use the \"old one\" anymore. If you need to use both implementations you\ncan still set the public and private keys in the fields, tags and widgets constructors.\n\n- ReCaptchaHiddenInput could be the starting point for the creation of some \"I'm not a robot\" reCAPTCHA template\ntags to use in place of the ReCaptchaWidget (maybe in a future release)\n\n## Testing\n### Test unit support\nYou can't simulate api calls in your test, but you can disable the recaptcha field and let your test works.\n\nJust set the RECAPTCHA_DISABLE env variable in your test:\n\n```python\nos.environ['RECAPTCHA_DISABLE'] = 'True'\n```\n\nWarning: you can use any word in place of \"True\", the clean function will check only if the variable exists.\n\n### Test unit with recaptcha2 disabled\n```python\nimport os\nimport unittest\n\nfrom yourpackage.forms import MyForm\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        os.environ['RECAPTCHA_DISABLE'] = 'True'\n\n    def test_myform(self):\n        form = MyForm({\n            'field1': 'field1_value'\n        })\n        self.assertTrue(form.is_valid())\n\n    def tearDown(self):\n        del os.environ['RECAPTCHA_DISABLE']\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkbytesys%2Fdjango-recaptcha2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkbytesys%2Fdjango-recaptcha2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkbytesys%2Fdjango-recaptcha2/lists"}