{ "info": { "author": "Simon Willison", "author_email": "simon+safeform@simonwillison.net", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP" ], "description": "django_safeform\n===============\n\nCSRF protection for Django implemented at the form level - no middleware \nrequired.\n\nThere are two steps to protecting a django.forms form:\n\n1. Wrap it with the SafeForm class decorator. This adds a hidden csrf_token \n field to it along with validation logic for checking if that token has \n the correct value. It also changes the signature of the form class \n slightly, see example below.\n2. Apply the @csrf_protect middleware to the view containing the form. This \n ensures that a _csrf_cookie is correctly set.\n\nRun \"./manage.py runserver\" in the examples folder to start a Django server \ndemonstrating the functionality of the library. Use \"./manage.py test\" in the \nsame directory to run the unit tests.\n\nExample usage::\n\n from django import forms\n from django.http import HttpResponse\n from django.shortcuts import render_to_response\n from django_safeform import SafeForm, csrf_protect\n \n class ChangePasswordForm(forms.Form):\n password = forms.CharField(widget = forms.PasswordInput)\n password2 = forms.CharField(widget = forms.PasswordInput)\n ChangePasswordForm = SafeForm(ChangePasswordForm)\n \n @csrf_protect\n def change_password(request):\n form = ChangePasswordForm(request) # A\n if request.method == 'POST':\n form = ChangePasswordForm(request, request.POST)\n if form.is_valid():\n # ... change the user's password here\n return HttpResponse('Thank you')\n return render_to_response('change_password.html', {\n 'form': form,\n })\n\nNote that the form constructor signature has changed - we now pass the request\nobject as the first argument.\n\nRevision history\n----------------\n\nv2.0.0 - 18 September 2009\n\nBreaks backward compatibility with previous release - no longer changes the \nform constructor signature to take just the request object and decide whether \nor not to bind the form based on the request method. You now need to make that \ndecision yourself in your view code (just as you do with regular Django \nforms). All examples and tests have been updated.\n\nAdded CsrfTestCase to test_utils, to simplify testing of CSRF protected forms.\n\nv1.0.1 - 17 September 2009\n\nDocumentation fixes.\n\nv1.0.0 - 17 September 2009\n\nInitial release.\n\nInstallation\n------------\n\ndjango-safeform is in PyPI: http://pypi.python.org/pypi/django-safeform ::\n\n pip install django-safeform\n - OR -\n easy_install django-safeform\n\nCustom form templates\n---------------------\n\nIf your template uses one of the form rendering helper methods such as \n{{ form.as_p }} the hidden csrf_token field will be output automatically. If \nyou are rendering the form using a custom template you will need to remember \nto output that field in your template explicitly. Here's an example::\n\n
\n\nNote the {{ form.csrf_token }} replacement variable just before the submit \nbutton - this will output a hidden form field containing the correct value.\n\nYou should also be sure to include {{ form.non_field_errors }} somewhere in \nyour template - this is where the \"Form session expired - please resubmit\" \nmessage will be displayed should the CSRF check fail for some reason.\n\nProtecting forms that do not use django.forms\n---------------------------------------------\n\nIf you are not using the django.forms framework - for example you are writing \nforms with hand-written HTML and pulling submitted data directly from \nrequest.POST - you can still add CSRF protection to your forms using the \n@csrf_protect decorator in conjunction with the csrf_utils module::\n\n from django_safeform import csrf_protect, csrf_utils\n \n @csrf_protect\n def hand_rolled(request):\n if request.method == 'POST':\n csrf_token = request.POST.get('csrf_token', '')\n if not csrf_utils.validate_csrf_token(csrf_token, request):\n return HttpResponse('Invalid CSRF token')\n else:\n return HttpResponse('OK')\n else:\n return HttpResponse(\"\"\"\n \n \"\"\" % csrf_utils.new_csrf_token(request))\n\nIt is your responsibility to include a hidden form field with the value from \ncsrf_utils.new_csrf_token(request) in your form, and to check that token when \nthe form is submitted using csrf_utils.validate_csrf_token.\n\nYou could also use CsrfForm to protect hand-written forms, as explained in \nthe next section.\n\nProtecting formsets / multiple forms on the same page\n-----------------------------------------------------\n\nIf you have multiple forms on the page and they are each contained in separate\n\n\nThe {{ csrf_form }} template tag specifies where the hidden input field \ncontaining the form token should be included. Should a CSRF failure occur, it \nalso specifies where the