Login

Honeypot Field

Author:
SmileyChris
Posted:
March 23, 2007
Language:
Python
Version:
.96
Score:
3 (after 3 ratings)

Simple anti-spam field which will cause the form to raise a ValidationError if the value in this field changes. Displays as a CSS hidden <input type="text" /> field.

If you specify a class in the attrs of the widget, the default style="display:none;" won't be rendered with the widget so that you can use a predefined CSS style to do your hiding instead. You can also cause the widget to be wrapped in an html comment to ensure it is not visible to the end user:

class EmailForm(Form):
    email = EmailField()
    website = HoneypotField(widget=HoneypotWidget(
                      attrs={'class':'fish'}, html_comment=True))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# In the following example, only the email field will be visible (the
# HoneypotFields are named as such to increase the chance that a bot
# will try to fill them in):
#
# class EmailForm(Form):
#    name = HoneypotField()
#    website = HoneypotField(initial='leave me')
#    email = EmailField()

from django.newforms import *

EMPTY_VALUES = (None, '')

class HoneypotWidget(TextInput):
    is_hidden = True
    def __init__(self, attrs=None, html_comment=False, *args, **kwargs):
        self.html_comment = html_comment
        super(HoneypotWidget, self).__init__(attrs, *args, **kwargs)
        if not self.attrs.has_key('class'):
            self.attrs['style'] = 'display:none'
    def render(self, *args, **kwargs):
        value = super(HoneypotWidget, self).render(*args, **kwargs)
        if self.html_comment:
            value = '<!-- %s -->' % value
        return value

class HoneypotField(Field):
    widget = HoneypotWidget
    def clean(self, value):
        if self.initial in EMPTY_VALUES and value in EMPTY_VALUES or value == self.initial:
            return value
        raise ValidationError('Anti-spam field changed in value.')

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 8 months, 3 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 3 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
  5. Help text hyperlinks by sa2812 1 year, 5 months ago

Comments

ericflo (on March 24, 2007):

This method of anti-spam seems intriguing, but I'm not sure that I am wrapping my head around it correctly.

Is this a field that you would add to an existing form to reduce fraudulent submissions of that form, or is it a field which you should create an entirely new and inactive form for, with the goal of attracting spam bots?

Also, in your example in your comments of the snippet, you have a name field as a HoneypotField. Does this suggest that the HoneypotField can be used to get input and not just thwart bots? I'm sure that there's just something that I'm missing, and if you could clarify that, I would be thankful because I need some anti-spam solutions soon myself!

#

SmileyChris (on March 24, 2007):

You add the field(s) to an existing form.

I called the field "name" because it's a common field which bots would probably try and change, it won't show up visually in the form.

I wouldn't rely on this solely as a method of stopping spam, but it could help reduce it.

#

ericflo (on March 24, 2007):

I see how it works--cool!

#

Xin (on May 6, 2007):

Sorry for my english, I'm catalan,

I have had an idea, but my experience with Django is little for develop myself.

The principle is use a system of human verification with a image digits or any type of question/response.

In a middleware, this load a system of question/response (base class), and put into context of template a variable form for print with a question and response inside anything <form></form>.

When the user post a form with his data and response verification, the middleware load response and question and send it to system question/response for validate the post data. Another form is use a decorator before view function for validate the response. Or use this as a simple function inside de view. (It can be configurable)

The limitation is that every time the middleware create a question/response and in a system with an image letters this can consume more time for create an image for question (except this use a set of know questions).

The advantage are: This can be tranparent to forms, views and models, and only afect to templates and view decorators. Other developers can write his systems question/response for adapt with his project.

#

mlissner (on May 31, 2011):

This works for django 1.2 if you switch the import line to: from django.forms import *

However, you still can't use it with ModelForms.

#

Please login first before commenting.