Style fixes, add missing docstring, fix some wrong calls to super classes and removal...
[Melange.git] / app / soc / views / helper / templatetags / forms_helpers.py
blobd71b9abe180270f6e86136ba660f3ba1f6ce3cb6
1 #!/usr/bin/python2.5
3 # Copyright 2008 the Melange authors.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """A Django template tag library containing forms helpers.
18 """
20 __authors__ = [
21 '"Todd Larsen" <tlarsen@google.com>',
22 '"Pawel Solyga" <pawel.solyga@gmail.com>',
23 '"Sverre Rabbelier" <sverre@rabbelier.nl>',
27 import re
29 from django import template
30 from django.forms import forms as forms_in
31 from django.utils.encoding import force_unicode
32 from django.utils.html import escape
34 from soc.logic import accounts
35 from soc.logic import dicts
36 from soc.views.helper import widgets
39 register = template.Library()
42 @register.inclusion_tag('soc/templatetags/_as_user.html')
43 def as_user(user):
44 """Prints a user as a hyperlinked link_id.
45 """
47 return {'user': user}
50 @register.inclusion_tag('soc/templatetags/_as_email.html')
51 def as_email(account):
52 """Prints a user as a hyperlinked link_id.
53 """
55 denormalized = accounts.denormalizeAccount(account)
57 return {'email': denormalized.email()}
60 @register.inclusion_tag('soc/templatetags/_field_as_table_row.html')
61 def field_as_table_row(field):
62 """Prints a newforms field as a table row.
64 This function actually does very little, simply passing the supplied
65 form field instance in a simple context used by the _field_as_table_row.html
66 template (which is actually doing all of the work).
68 See soc/templates/soc/templatetags/_field_as_table_row.html for the CSS
69 styles used by this template tag.
71 Usage:
72 {% load forms_helpers %}
73 ...
74 <table>
75 {% field_as_table_row form.fieldname %}
76 ...
77 </table>
79 Args:
80 field: a Django newforms field instance
82 Returns:
83 a simple context containing the supplied newforms field instance:
84 { 'field': field }
85 """
86 return {'field': field}
89 @register.inclusion_tag('soc/templatetags/_readonly_field_as_table_row.html')
90 def readonly_field_as_table_row(label, value):
91 """Prints a field value and it's verbose name as a table row.
93 This function actually does very little, simply passing the
94 supplied field_label and field_value in a simple context used by the
95 _readonly_field_as_table_row.html template (which is actually
96 doing all of the work).
98 See soc/templates/soc/templatetags/_readonly_field_as_table_row.html for
99 the CSS styles used by this template tag.
101 Usage:
102 {% load forms_helpers %}
104 <table>
105 {% readonly_field_as_table_row field_label field_value %}
107 </table>
109 Args:
110 field_label: label of the field to render
111 field_value: value of the field to render
113 Returns:
114 a simple context containing the supplied newforms field instance:
115 { 'field_label': field_label',
116 'field_value': field_value'}
119 value = value.strip() if isinstance(value, basestring) else value
121 return {'field_label': label,
122 'field_value': value}
125 @register.inclusion_tag(
126 'soc/templatetags/_readonly_field_as_twoline_table_row.html')
127 def readonly_field_as_twoline_table_row(label, value):
128 """See readonly_field_as_table_row().
131 value = value.strip() if isinstance(value, basestring) else value
133 return {'field_label': label,
134 'field_value': value}
137 @register.inclusion_tag(
138 'soc/templatetags/_readonly_url_field_as_table_row.html')
139 def readonly_url_field_as_table_row(field_label, field_value):
140 """See readonly_field_as_table_row().
142 return {'field_label': field_label,
143 'field_value': field_value}
146 @register.inclusion_tag(
147 'soc/templatetags/_readonly_url_field_as_twoline_table_row.html')
148 def readonly_url_field_as_twoline_table_row(field_label, field_value):
149 """See readonly_field_as_table_row().
151 return {'field_label': field_label,
152 'field_value': field_value}
155 @register.inclusion_tag(
156 'soc/templatetags/_readonly_safe_field_as_table_row.html')
157 def readonly_safe_field_as_table_row(field_label, field_value):
158 """See readonly_field_as_table_row().
160 return {'field_label': field_label,
161 'field_value': field_value}
164 @register.inclusion_tag(
165 'soc/templatetags/_readonly_safe_field_as_twoline_table_row.html')
166 def readonly_safe_field_as_twoline_table_row(field_label, field_value):
167 """See readonly_field_as_table_row().
169 return {'field_label': field_label,
170 'field_value': field_value}
173 @register.inclusion_tag('soc/templatetags/_as_readonly_table.html',
174 takes_context=True)
175 def as_readonly_table(context, form):
176 """Outputs a form as a properly formatted html table.
178 Args:
179 form: the form that should be converted to a table
182 # create the bound fields
183 fields = [forms_in.BoundField(form, field, name) for name, field in
184 form.fields.items() if field]
186 return {'fields': fields}
188 @register.inclusion_tag('soc/templatetags/_as_table.html', takes_context=True)
189 def as_table(context, form):
190 """Outputs a form as a properly formatted html table.
192 Args:
193 form: the form that should be converted to a table
196 return as_table_helper(context, form)
199 @register.inclusion_tag('soc/templatetags/_as_twoline_table.html',
200 takes_context=True)
201 def as_twoline_table(context, form):
202 """Outputs a form as a properly formatted html table.
204 Args:
205 form: the form that should be converted to a table
208 return as_table_helper(context, form)
211 def as_table_helper(context, form):
212 """See as_table().
215 fields = []
216 hidden_fields = []
217 hidden_fields_errors = []
218 errors = False
220 # entity = context['entity']
222 # Iterate over all fields and prepare it for adding
223 for name, field in form.fields.items():
224 if not field:
225 continue
227 bf = forms_in.BoundField(form, field, name)
228 attrs = {}
230 if isinstance(field, widgets.ReferenceField):
231 attrs = field.rf
233 # If the field is hidden we display it elsewhere
234 if not bf.is_hidden:
235 if bf.errors:
236 errors = True
238 example_text = ''
239 group = '0. '
241 if hasattr(field, 'group'):
242 group = field.group
244 if hasattr(field, 'example_text'):
245 example_text = force_unicode(field.example_text)
247 item = {
248 'field': bf,
249 'required': field.required,
250 'example_text': example_text,
251 'group': group,
254 item.update(attrs)
255 fields.append(item)
256 else:
257 hidden_fields.append(unicode(bf))
259 for error in bf.errors:
260 item = (name, force_unicode(error))
261 hidden_fields_errors.append(item)
263 grouped = dicts.groupby(fields, 'group')
264 rexp = re.compile(r"\d+. ")
265 fields = [(rexp.sub('', key), grouped[key]) for key in sorted(grouped)]
267 context.update({
268 'top_errors': form.non_field_errors() or '',
269 'hidden_field_errors': hidden_fields_errors or '',
270 'errors': errors,
271 'groups': fields if fields else '',
272 'hidden_fields': hidden_fields or '',
275 return context
278 @register.inclusion_tag('soc/templatetags/_as_table_row.html',
279 takes_context=True)
280 def as_table_row(context, item):
281 """Outputs a field as a properly formatted html row.
283 Args:
284 item: the item that is being rendered
287 return as_table_row_helper(context, item)
290 @register.inclusion_tag('soc/templatetags/_as_twoline_table_row.html',
291 takes_context=True)
292 def as_twoline_table_row(context, item):
293 """See as_table_row().
296 return as_table_row_helper(context, item)
299 def as_table_row_helper(context, item):
300 """See as_table_row().
303 field = item['field']
304 required = item['required']
305 example_text = item['example_text']
307 form = context['form']
308 entity = context['entity']
310 reference = item.get('reference_url')
311 filter = item.get('filter')
312 filter_fields = item.get('filter_fields')
314 # Escape and cache in local variable.
315 errors = [force_unicode(escape(error)) for error in field.errors]
318 if reference:
319 from soc.views.helper import redirects
320 params = {
321 'url_name': reference,
324 if entity:
325 args = {}
326 for filter_field, filter_value in filter_fields.iteritems():
327 args[filter_field] = filter_value
328 for filter_field in (i for i in filter if hasattr(entity, i)):
329 args[filter_field] = getattr(entity, filter_field)
331 if '__scoped__' in filter:
332 args['scope_path'] = entity.key().name()
334 params['args'] = '&'.join(['%s=%s' % item for item in args.iteritems()])
336 select_url = redirects.getSelectRedirect(params)
338 if field.label:
339 label = escape(force_unicode(field.label))
341 # Only add the suffix if the label does not end in punctuation.
342 if form.label_suffix and (label[-1] not in ':?.!'):
343 label += form.label_suffix
345 label = field.label_tag(label) or ''
347 field_class_type = 'formfield%slabel' % ('error' if errors else '')
349 help_text = field.help_text
351 context.update({
352 'help_text': force_unicode(help_text) if help_text else '',
353 'field_class_type': field_class_type,
354 'label': force_unicode(label) if field.label else '',
355 'field': field,
356 'field_id': field.auto_id,
357 'required': required,
358 'example_text': example_text,
359 'select_url': select_url if reference else None,
360 'errors': errors,
363 return context