Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added "use_csrf_protection" option to FormHelper in order to render

the csrf token in forms (as required by Django 1.2).

The new option is set to False by default in order to keep backwards
compatibility.
  • Loading branch information...
commit 3ced843e8aecc6e6ad42e6f37149158bfda46979 1 parent ad521d7
Casper S. Jensen authored pydanny committed
View
91 uni_form/helpers.py
@@ -26,9 +26,9 @@ class Submit(BaseInput):
submit = Submit('Search the Site','search this site')
Note: The first argument is also slugified and turned into the id for the submit button.
-
+
"""
-
+
input_type = 'submit'
field_classes = 'submit submitButton'
@@ -41,7 +41,7 @@ class Button(BaseInput):
Note: The first argument is also slugified and turned into the id for the button.
"""
-
+
input_type = 'button'
field_classes = 'button'
@@ -49,7 +49,7 @@ class Hidden(BaseInput):
"""
Used to create a Hidden input descriptor for the uni_form template tag.
"""
-
+
input_type = 'hidden'
field_classes = 'hidden'
@@ -60,9 +60,9 @@ class Reset(BaseInput):
reset = Reset('Reset This Form','Revert Me!')
Note: The first argument is also slugified and turned into the id for the reset.
-
+
"""
-
+
input_type = 'reset'
field_classes = 'reset resetButton'
@@ -116,9 +116,9 @@ def render(self, form):
return html
class Fieldset(object):
-
+
''' Fieldset container. Renders to a <fieldset>. '''
-
+
def __init__(self, legend, *fields, **args):
if 'css_class' in args.keys():
self.css = args['css_class']
@@ -126,8 +126,8 @@ def __init__(self, legend, *fields, **args):
self.css = None
self.legend_html = legend and ('<legend>%s</legend>' % unicode(legend)) or ''
self.fields = fields
-
-
+
+
def render(self, form):
if self.css:
html = u'<fieldset class="%s">' % self.css
@@ -149,7 +149,7 @@ def __init__(self, *fields, **kwargs):
self.css = kwargs['css_class']
else:
self.css = "formRow"
-
+
def render(self, form):
output = u'<div class="%s">' % self.css
for field in self.fields:
@@ -165,7 +165,7 @@ def __init__(self, *fields, **kwargs):
self.css = kwargs['css_class']
else:
self.css = "formColumn"
-
+
def render(self, form):
output = u'<div class="%s">' % self.css
for field in self.fields:
@@ -174,12 +174,12 @@ def render(self, form):
return u''.join(output)
class HTML(object):
-
+
''' HTML container '''
-
+
def __init__(self, html):
self.html = unicode(html)
-
+
def render(self, form):
return self.html
@@ -191,29 +191,36 @@ class FormHelper(object):
By setting attributes to me you can easily create the text that goes
into the uni_form template tag. One use case is to add to your form
class.
-
+
Special attribute behavior:
-
+
method: Defaults to POST but you can also do 'GET'
-
+
form_action: applied to the form action attribute. Can be a named url in
your urlconf that can be executed via the *url* default template tag or can
simply point to another URL.
-
+
id: Generates a form id for dom identification.
If no id provided then no id attribute is created on the form.
-
+
class: add space seperated classes to the class list.
Defaults to uniForm.
Always starts with uniForm even do specify classes.
form_tag: Defaults to True. If set to False it renders the form without the form tags.
-
+ use_csrf_protection: Defaults to False. If set to True a CSRF protection token is
+ rendered in the form. This should only be left as False for forms targeting
+ external sites or internal sites without CSRF protection (as described in the
+ Django documentation).
+ Requires the presence of a csrf token in the current context with the identifier
+ "csrf_token" (which is automatically added to your context when using RequestContext).
+
+
Demonstration:
-
+
First we create a MyForm class and instantiate it
-
+
>>> from django import forms
>>> from uni_form.helpers import FormHelper, Submit, Reset
>>> from django.utils.translation import ugettext_lazy as _
@@ -227,15 +234,15 @@ class FormHelper(object):
... helper.add_input(submit)
... reset = Reset('reset','reset button')
... helper.add_input(reset)
-
+
After this in the template::
-
+
{% load uni_form_tags %}
{% uni_form form form.helper %}
-
-
+
+
"""
-
+
def __init__(self):
self._form_method = 'post'
self._form_action = ''
@@ -245,46 +252,48 @@ def __init__(self):
self.toggle = Toggle()
self.layout = None
self.form_tag = True
-
+ self.use_csrf_protection = False
+
def get_form_method(self):
return self._form_method
-
+
def set_form_method(self, method):
if method.lower() not in ('get','post'):
raise FormHelpersException('Only GET and POST are valid in the \
form_method helper attribute')
-
+
self._form_method = method.lower()
-
+
# we set properties the old way because we want to support pre-2.6 python
form_method = property(get_form_method, set_form_method)
-
+
def get_form_action(self):
return self._form_action
-
+
def set_form_action(self, action):
try:
self._form_action = reverse(action)
except NoReverseMatch:
self._form_action = action
-
+
# we set properties the old way because we want to support pre-2.6 python
form_action = property(get_form_action, set_form_action)
-
+
def add_input(self, input_object):
self.inputs.append(input_object)
-
+
def add_layout(self, layout):
self.layout = layout
-
+
def render_layout(self, form):
return mark_safe(self.layout.render(form))
-
+
def get_attr(self):
items = {}
items['form_method'] = self.form_method.strip()
items['form_tag'] = self.form_tag
-
+ items['use_csrf_protection'] = self.use_csrf_protection
+
if self.form_action:
items['form_action'] = self.form_action.strip()
if self.form_id:
@@ -296,4 +305,4 @@ def get_attr(self):
if self.toggle.fields:
items['toggle_fields'] = self.toggle.fields
return items
-
+
View
3  uni_form/templates/uni_form/whole_uni_form.html
@@ -2,6 +2,7 @@
{% if form_tag %}<form action="{{ form_action|lower }}" class="uniForm{% if form_class %} {% endif %}{{ form_class }}" method="{{ form_method }}"{% if form_id %} id="{{ form_id|slugify }}"{% endif %}{% if form.is_multipart %} enctype="multipart/form-data"{% endif %}>{% endif %}
+ {% csrf_token %}
{% if form.non_field_errors %}
<div id="errorMsg">
<h3>{% if error_message_title %}{{ error_message_title }}{% else %}Errors{% endif %}</h3>
@@ -10,7 +11,7 @@
</ol>
</div>
{% endif %}
- {% if form_html %}{{ form_html }}{% else %}
+ {% if form_html %}{{ form_html }}{% else %}
<fieldset class="inlineLabels">
<legend>* {% trans "Required fields" %}</legend>
{% for field in form %}
View
58 uni_form/templatetags/uni_form_tags.py
@@ -71,11 +71,11 @@ class BasicNode(template.Node):
will need both the form object and the helper string. This handles
both the form object and parses out the helper string into attributes
that templates can easily handle. """
-
+
def __init__(self, form, helper):
self.form = template.Variable(form)
self.helper = template.Variable(helper)
-
+
def get_render(self, context):
actual_form = self.form.resolve(context)
helper = self.helper.resolve(context)
@@ -91,6 +91,7 @@ def get_render(self, context):
form_tag = True
inputs = []
toggle_fields = set(())
+ use_csrf_protection = False
if attrs:
form_tag = attrs.get("form_tag", True)
form_method = attrs.get("form_method", form_method)
@@ -99,13 +100,14 @@ def get_render(self, context):
form_id = attrs.get("id", "")
inputs = attrs.get('inputs', [])
toggle_fields = attrs.get('toggle_fields', set(()))
+ use_csrf_protection = attrs.get('use_csrf_protection', False)
final_toggle_fields = []
if toggle_fields:
final_toggle_fields = []
for field in actual_form:
if field.auto_id in toggle_fields:
final_toggle_fields.append(field)
-
+
if helper and helper.layout:
form_html = helper.render_layout(actual_form)
else:
@@ -122,6 +124,10 @@ def get_render(self, context):
'inputs' : inputs,
'toggle_fields': final_toggle_fields
}
+
+ if use_csrf_protection and context.has_key('csrf_token'):
+ response_dict['csrf_token'] = context['csrf_token']
+
c = Context(response_dict)
return c
@@ -135,40 +141,40 @@ def get_render(self, context):
@register.tag(name="uni_form")
def do_uni_form(parser, token):
-
+
"""
You need to pass in at least the form object, and can also pass in the
optional helper object. Writing the attrs string is rather challenging so
use of the objects found in uni_form.helpers is encouraged.
-
+
form: The forms object to be rendered by the tag
-
+
helper (optional): A uni_form.helpers.FormHelper object.
-
+
Example::
-
+
{% uni_form my-form my_helper %}
-
+
"""
-
+
token = token.split_contents()
-
+
form = token.pop(1)
try:
helper = token.pop(1)
except IndexError:
helper = None
-
-
+
+
return UniFormNode(form, helper)
class UniFormNode(BasicNode):
-
+
def render(self, context):
-
+
c = self.get_render(context)
-
+
template = get_template('uni_form/whole_uni_form.html')
return template.render(c)
@@ -182,27 +188,27 @@ def uni_form_jquery(parser, token):
"""
toggle_field: For making fields designed to be toggled for editing add them
by spaces. You must specify by field id (field.auto_id)::
-
+
toggle_fields=<first_field>,<second_field>
-
+
"""
-
+
token = token.split_contents()
-
+
form = token.pop(1)
try:
attrs = token.pop(1)
except IndexError:
attrs = None
-
-
+
+
return UniFormJqueryNode(form,attrs)
class UniFormJqueryNode(BasicNode):
-
+
def render(self,context):
-
+
c = self.get_render(context)
-
+
template = get_template('uni_form/uni_form_jquery.html')
- return template.render(c)
+ return template.render(c)
Please sign in to comment.
Something went wrong with that request. Please try again.