Due to recent spammers/bots attempting to create comments, which leads me to having to remove them and block them entirely. I decided to develop an idea I built a few years ago. The idea came to me when I thought of how bots work and understand forms. They normally check for common field types and fill those in. Essentially what I did, is take way those easy to see field types in the HTML form. Now a comments form in Django is rendered in HTML like follows:
<form action="/comments/post/" method="post">
<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='7608951b675fe0b286951df9880276e8' /></div>
<input name="KRGRTNRWA" value="" type="hidden" />
<input name="RQGKZWFSK" value="blog.entry" type="hidden" />
<input name="DPCOMKEJS" value="68" type="hidden" />
<input name="TUSGZBKQE" value="1351495666" type="hidden" />
<input name="ICOHFKUPI" value="fb931472ccb6344f941e6416091d73706c92332e" type="hidden" />
<input name="KZQBWXPSX" value="" type="text" />
<input name="EAAAJQLNT" value="" type="text" />
<input name="OTVHKQTVY" value="" type="text" />
<textarea name="MPBQIMIKS" id="id_comment" cols="80" rows="10"></textarea>
<input name="IAUXROHTG" value="" type="hidden" />
<input type="hidden" name="auth" value="1d5d9efa72ee52386563aab8c8d573f1" />
<input class="btn btn-primary" type="submit" value="Post Comment">
</form>
It's hard to tell what needs to be filled out with what. If the server-side validation fails for a field, it's back to trying again and again until it validates for a successful comments post. Now your most likely thinking... Well, once they find out the pattern, they've basically cracked it and can start spamming with the new field names... No so fast... You didn't let me finish. These random ASCII letters you see there... They are randomly generated on each request, and are unique for that request. Well, what if they found out how to generate their own data in order to use the same field names over and over... I've thought of that too! The magic of this is, that it is absolutely bound to a single request no matter what. There's no way to trick the system. On the server-side, there are plenty of checks to make sure that everything is absolutely in check before even looking at the data and attempting to see what fits where.
I may open source this code, since it does utilize the SECRET_KEY in Django. These types of forms may help others as well, and open sourcing it might even make the code better... The code is sort of messy right now, and not properly attached to the Django forms class. It is currently built using it's own class and special constructor. Once the data is verified and valid, the code can then pass the posted data over to a standard Django form for handling. So, this can use Django forms, and model forms. However, this special class acts as a proxy between the POST data and the Django forms API. Here's a simple code example of what the backend does:
def my_view(req):
frm = DynamicForm(req)
frm.addField('text', 'name')
frm.addField('text', 'age')
frm.addField('textarea', 'bio')
if req.method == 'POST':
if frm.is_valid():
form = ContactForm(frm.getFields())
if form.is_valid():
return HttpResponse('Form was valid: %s' % form.cleaned_data['name'])
return render_to_response("dynamic_form.html", {'form':frm}, context_instance=RequestContext(req))
This is actual code I used during the testing of this new forms system, as I said, it's messy. Currently, it doesn't interface with Django's forms API, which is a complete shame. Since it doesn't read Django's forms, this can technically be used with any Python web framework, which is a positive about it. You can see from above, that it needs to declare the form, once the form is declared, it is validated. Once the validation is complete, it passes a standard dict of the POST data over to the real Django form for processing. Also, rather than passing a Django form to a template, you pass this special form over for rendering. This class basically manages the special mappings used in the HTML form code.
You can try out the comments form below and take a peek at it's source code as well. If you plan on submitting a comment, be sure you haven't visited other parts of this site which use the comments form. Currently, since this uses state-fulness, only one comments form is currently supported on a single domain. Although for most applications, this shouldn't really matter.
