===============
django-honeypot
===============
.. image:: https://github.com/jamesturk/django-honeypot/actions/workflows/test.yml/badge.svg
.. image:: https://img.shields.io/pypi/v/django-honeypot.svg
:target: https://pypi.python.org/pypi/django-honeypot
Django application that provides utilities for preventing automated form spam.
Provides template tags, view decorators, and middleware to add and verify honeypot fields to forms.
Written by James Turk with contributions by Flavio Curella and Daniel Greenfeld.
Source: https://github.com/jamesturk/django-honeypot/
Requirements
============
* python >= 3.8
* django >= 3.2
Usage
=====
settings.py
-----------
Be sure to add ``honeypot`` to ``INSTALLED_APPS`` in settings.py.
You will almost always need to define ``HONEYPOT_FIELD_NAME`` which is the name to use for the honeypot field. Some sophisticated bots will attempt to avoid fields named honeypot, so it may be wise to name the field something slightly more realistic such as "phonenumber" or "body2".
``HONEYPOT_VALUE`` is an option that you can specify to populate the honeypot field, by default the honeypot field will be empty and any text entered into it will result in a failed POST. ``HONEYPOT_VALUE`` can be a string or a callable that takes no arguments.
``HONEYPOT_VERIFIER`` is an advanced option that you can specify to validate the honeypot. The default verifier ensures that the contents of the honeypot field matches ``HONEYPOT_VALUE``. Using a combination of a callable for ``HONEYPOT_VALUE`` and ``HONEYPOT_VERIFIER`` it is possible to implement a more advanced technique such as using timestamps.
``HONEYPOT_RESPONDER`` can be used to replace the default response in case of an invalid honeypot.
Adding honeypot fields to specific forms and views
--------------------------------------------------
It is possible to add honeypot fields to specific forms and ensure that specific views check for a valid honeypotin ``request.POST``. This can be accomplished by using the ``render_honeypot_field`` template tag:
At the top of a template file include the line::
{% load honeypot %}
And then within any form including the tag::
{% render_honeypot_field "field_name" %}
will render a honeypot field named "field_name" that is hidden by default. The name of the honeypot field will default to ``HONEYPOT_FIELD_NAME`` if one is not provided.
To ensure that the honeypot field is both present and correct you will need to use ``check_honeypot`` decorator from ``honeypot.decorators``:
.. code:: python
from honeypot.decorators import check_honeypot
@check_honeypot(field_name='hp_field_name')
def post_comment(request):
...
@check_honeypot
def other_post_view(request):
...
This decorator will ensure that a field exists in ``request.POST`` that is named 'field_name'. ``@check_honeypot`` without arguments will use the default ``HONEYPOT_FIELD_NAME``.
Adding honeypot fields to class-based-views
-------------------------------------------
The same as above for `Adding honeypot fields to specific forms and views`_ but add the decorator to the post method making use of django's `method_decorator <https://docs.djangoproject.com/en/3.2/topics/class-based-views/intro/#decorating-the-class>`_.
.. code:: python
from django.utils.decorators import method_decorator
from honeypot.decorators import check_honeypot
@method_decorator(check_honeypot, name='post')
class MyView(FormView):
...
Adding honeypot fields site-wide
--------------------------------
Sometimes it is desirable to add honeypots to all forms site-wide. This is particularly useful when dealing with apps that render their own forms. For this purpose three middlewares are provided, similar in functionality to django's own CSRF middleware.
All of these middleware live in ``honeypot.middleware``.
``HoneypotResponseMiddleware`` analyzes the output of all responses and rewrites any forms that use ``method="POST"`` to contain a honeypot field, just as if they had started with ``{% render_honeypot_field %}``. Borrowing heavily from ``django.contrib.csrf.middleware.CsrfResponseMiddleware`` this middleware only rewrites responses with Content-Type text/html or application/xhtml+xml.
``HoneypotViewMiddleware`` ensures that for all incoming POST requests to views ``request.POST`` contains a valid honeypot field as defined by the ``HONEYPOT_FIELD_NAME``, ``HONEYPOT_VALUE``, and ``HONEYPOT_VERIFIER`` settings. The result is the same as if every view in your project were decorated with ``@check_honeypot``.
``HoneypotMiddleware`` is a combined middleware that applies both ``HoneypotResponseMiddleware`` and ``HoneypotViewMiddleware``, this is the easiest way to get honeypot fields site-wide and can be used in many if not most cases. The middleware needs to be listed after ``CommonMiddleware`` because the middleware changes the response. If you list it before ``CommonMiddleware`` then the ``Content-Length`` header won't reflect the changes.
Customizing honeypot display
----------------------------
There are two templates used by django-honeypot that can be used to control various aspects of how the honeypot functionality is presented to the user.
``honeypot/honeypot_field.html`` is used to render the honeypot field. It is given two context variables ``fieldname`` and ``value``, corresponding to ``HONEYPOT_FIELD_NAME`` and ``HONEYPOT_VALUE`` or any overrides in effect (such as a custom field name passed to the template tag).
``honeypot/honeypot_error.html`` is the error page rendered when a bad request is intercepted. It is given the context variable ``fieldname`` representing the name of the honeypot field.
To completely change the error page or what happens when a bad request is intercepted set ``HONEYPOT_RESPONDER`` to a function accepting ``request`` and ``context`` kwargs and returning a ``HttpResponse``.
.. code:: python
# mypackage.py
from honeypot.decorators import honeypot_error
def custom_honeypot_error(request, context):
# custom responder logging the event
log.warning("gotcha!")
# call built-in responder to send default HttpResponseBadRequest
return honeypot_error(request, context)
# or ...
# raise Http404
.. code:: python
# settings.py
from django.utils.module_loading import import_string
HONEYPOT_RESPONDER = import_string('mypackage.custom_honeypot_error')
Raw data
{
"_id": null,
"home_page": "https://github.com/jamesturk/django-honeypot/",
"name": "django-honeypot",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": null,
"author": "James Turk",
"author_email": "dev@jamesturk.net",
"download_url": "https://files.pythonhosted.org/packages/e2/8f/0bcf3f10ec08720086ab625dddfa061f8534cf06b16eb7567b0cc9242f4f/django_honeypot-1.2.1.tar.gz",
"platform": null,
"description": "===============\ndjango-honeypot\n===============\n\n.. image:: https://github.com/jamesturk/django-honeypot/actions/workflows/test.yml/badge.svg\n\n.. image:: https://img.shields.io/pypi/v/django-honeypot.svg\n :target: https://pypi.python.org/pypi/django-honeypot\n\nDjango application that provides utilities for preventing automated form spam.\n\nProvides template tags, view decorators, and middleware to add and verify honeypot fields to forms.\n\nWritten by James Turk with contributions by Flavio Curella and Daniel Greenfeld.\n\nSource: https://github.com/jamesturk/django-honeypot/\n\nRequirements\n============\n\n* python >= 3.8\n* django >= 3.2\n\nUsage\n=====\n\nsettings.py\n-----------\n\nBe sure to add ``honeypot`` to ``INSTALLED_APPS`` in settings.py.\n\nYou will almost always need to define ``HONEYPOT_FIELD_NAME`` which is the name to use for the honeypot field. Some sophisticated bots will attempt to avoid fields named honeypot, so it may be wise to name the field something slightly more realistic such as \"phonenumber\" or \"body2\".\n\n``HONEYPOT_VALUE`` is an option that you can specify to populate the honeypot field, by default the honeypot field will be empty and any text entered into it will result in a failed POST. ``HONEYPOT_VALUE`` can be a string or a callable that takes no arguments.\n\n``HONEYPOT_VERIFIER`` is an advanced option that you can specify to validate the honeypot. The default verifier ensures that the contents of the honeypot field matches ``HONEYPOT_VALUE``. Using a combination of a callable for ``HONEYPOT_VALUE`` and ``HONEYPOT_VERIFIER`` it is possible to implement a more advanced technique such as using timestamps.\n\n``HONEYPOT_RESPONDER`` can be used to replace the default response in case of an invalid honeypot.\n\nAdding honeypot fields to specific forms and views\n--------------------------------------------------\n\nIt is possible to add honeypot fields to specific forms and ensure that specific views check for a valid honeypotin ``request.POST``. This can be accomplished by using the ``render_honeypot_field`` template tag:\n\nAt the top of a template file include the line::\n\n {% load honeypot %}\n\nAnd then within any form including the tag::\n\n {% render_honeypot_field \"field_name\" %}\n\nwill render a honeypot field named \"field_name\" that is hidden by default. The name of the honeypot field will default to ``HONEYPOT_FIELD_NAME`` if one is not provided.\n\nTo ensure that the honeypot field is both present and correct you will need to use ``check_honeypot`` decorator from ``honeypot.decorators``:\n\n.. code:: python\n\n from honeypot.decorators import check_honeypot\n\n @check_honeypot(field_name='hp_field_name')\n def post_comment(request):\n ...\n\n @check_honeypot\n def other_post_view(request):\n ...\n\nThis decorator will ensure that a field exists in ``request.POST`` that is named 'field_name'. ``@check_honeypot`` without arguments will use the default ``HONEYPOT_FIELD_NAME``.\n\nAdding honeypot fields to class-based-views\n-------------------------------------------\n\nThe same as above for `Adding honeypot fields to specific forms and views`_ but add the decorator to the post method making use of django's `method_decorator <https://docs.djangoproject.com/en/3.2/topics/class-based-views/intro/#decorating-the-class>`_.\n\n\n.. code:: python\n\n from django.utils.decorators import method_decorator\n from honeypot.decorators import check_honeypot\n\n @method_decorator(check_honeypot, name='post')\n class MyView(FormView):\n ...\n\nAdding honeypot fields site-wide\n--------------------------------\n\nSometimes it is desirable to add honeypots to all forms site-wide. This is particularly useful when dealing with apps that render their own forms. For this purpose three middlewares are provided, similar in functionality to django's own CSRF middleware.\n\nAll of these middleware live in ``honeypot.middleware``.\n\n``HoneypotResponseMiddleware`` analyzes the output of all responses and rewrites any forms that use ``method=\"POST\"`` to contain a honeypot field, just as if they had started with ``{% render_honeypot_field %}``. Borrowing heavily from ``django.contrib.csrf.middleware.CsrfResponseMiddleware`` this middleware only rewrites responses with Content-Type text/html or application/xhtml+xml.\n\n``HoneypotViewMiddleware`` ensures that for all incoming POST requests to views ``request.POST`` contains a valid honeypot field as defined by the ``HONEYPOT_FIELD_NAME``, ``HONEYPOT_VALUE``, and ``HONEYPOT_VERIFIER`` settings. The result is the same as if every view in your project were decorated with ``@check_honeypot``.\n\n``HoneypotMiddleware`` is a combined middleware that applies both ``HoneypotResponseMiddleware`` and ``HoneypotViewMiddleware``, this is the easiest way to get honeypot fields site-wide and can be used in many if not most cases. The middleware needs to be listed after ``CommonMiddleware`` because the middleware changes the response. If you list it before ``CommonMiddleware`` then the ``Content-Length`` header won't reflect the changes.\n\nCustomizing honeypot display\n----------------------------\n\nThere are two templates used by django-honeypot that can be used to control various aspects of how the honeypot functionality is presented to the user.\n\n``honeypot/honeypot_field.html`` is used to render the honeypot field. It is given two context variables ``fieldname`` and ``value``, corresponding to ``HONEYPOT_FIELD_NAME`` and ``HONEYPOT_VALUE`` or any overrides in effect (such as a custom field name passed to the template tag).\n\n``honeypot/honeypot_error.html`` is the error page rendered when a bad request is intercepted. It is given the context variable ``fieldname`` representing the name of the honeypot field.\n\nTo completely change the error page or what happens when a bad request is intercepted set ``HONEYPOT_RESPONDER`` to a function accepting ``request`` and ``context`` kwargs and returning a ``HttpResponse``.\n\n.. code:: python\n\n # mypackage.py\n from honeypot.decorators import honeypot_error\n\n def custom_honeypot_error(request, context):\n # custom responder logging the event\n log.warning(\"gotcha!\")\n # call built-in responder to send default HttpResponseBadRequest\n return honeypot_error(request, context)\n # or ...\n # raise Http404\n\n.. code:: python\n\n # settings.py\n from django.utils.module_loading import import_string\n\n HONEYPOT_RESPONDER = import_string('mypackage.custom_honeypot_error')\n",
"bugtrack_url": null,
"license": "BSD-2-Clause",
"summary": "Django honeypot field utilities",
"version": "1.2.1",
"project_urls": {
"Homepage": "https://github.com/jamesturk/django-honeypot/",
"Repository": "https://github.com/jamesturk/django-honeypot/"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "0cc96372492315f3c219c81fb711769bc9522a9bbe90d96eed3114270eec6635",
"md5": "5cca0df82717506fc3d70f8f1cef09ba",
"sha256": "fdabe4ded66b6db25d04af2446de3bf7cb047cb5db097a864c8c97b081ef736f"
},
"downloads": -1,
"filename": "django_honeypot-1.2.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "5cca0df82717506fc3d70f8f1cef09ba",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 10892,
"upload_time": "2024-08-03T19:25:31",
"upload_time_iso_8601": "2024-08-03T19:25:31.689586Z",
"url": "https://files.pythonhosted.org/packages/0c/c9/6372492315f3c219c81fb711769bc9522a9bbe90d96eed3114270eec6635/django_honeypot-1.2.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e28f0bcf3f10ec08720086ab625dddfa061f8534cf06b16eb7567b0cc9242f4f",
"md5": "5fbc9bd5ece7f217754cd931c5acdaaa",
"sha256": "ab5c2aad214d86def2f00f6a79aa14f171db7301ac8712f20dc21a83dd5d6413"
},
"downloads": -1,
"filename": "django_honeypot-1.2.1.tar.gz",
"has_sig": false,
"md5_digest": "5fbc9bd5ece7f217754cd931c5acdaaa",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 10185,
"upload_time": "2024-08-03T19:25:33",
"upload_time_iso_8601": "2024-08-03T19:25:33.625411Z",
"url": "https://files.pythonhosted.org/packages/e2/8f/0bcf3f10ec08720086ab625dddfa061f8534cf06b16eb7567b0cc9242f4f/django_honeypot-1.2.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-03 19:25:33",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jamesturk",
"github_project": "django-honeypot",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "django-honeypot"
}