If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

The problem

A view page such as

{{extend 'layout.html'}}
<br />

will produce a nice recursively traversed presentation showing keys and values of the dictionary output of the relevant controller function in a table. If a key value points to an inner dictionary, list or tuple then the value is recursed and shown as a table within a table and so on. Very convenient.

There are two problems

  1. The order of presentation of keys at a particular dictionary recursion level is alphabetical.
  2. Using the dict method is common in web2py to construct a dictionary. However with this method keys cannot have spaces in them and so the key will not appear as words when displayed in a view

The solution

As of 17 February 2010 there is a new version of BEAUTIFY in the web2py trunk that accepts a key filter attribute. A sample of how to use the filter is shown that does not require the BEAUTIFY class to be altered.

The last four lines of the six lines below are an addition to prior versions of BEAUTIFY in file gluon\html.py and provides a solution without altering the normal behaviour of BEAUTIFY.

if type(value) == types.LambdaType:
if isinstance(key, str):  # a key must be a string type
  if key[1]=='_':         # 'a_bcde_fghi' means 'bcde_fghi' is the key to be shown
  key=key[2:]             # remove 'a_' from 'a_bcde_fghi'
  key=' '.join([x.capitalize() for x in key.split('_')])  # Converts remaining 'bcde_fghi' to 'Bcde Fghi'

The last three lines above can be replaced by the single line statement

  key=' '.join([x.capitalize() for x in key[2:].split('_')]) if key[1:2]=='_' else key

This is important as this statement can be passed with a lambda into the new version of BEAUTIFY without modification to BEAUTIFY. The functionality of the last fourth line is not necessary when a view will only be used with a controller function that returns dictionaries prepared with the dict method; as keys of dict methods can only be strings. Alternatively a safer single statement version that replaces all the last four lines is

  key=' '.join([x.capitalize() for x in key[2:].split('_')]) if isinstance(key, str) and key[1:2]=='_' else key

The code examines the second character of the key. If this character is '_' it removes the first two characters. This means the single characters A-Z, a-z and 0-9 are available to arbitrarily and conveniently reorder presentation independent of alphabetic order, as the first letter and the underscore following will be removed.

Also if the second character is '_', then the last line the of code replaces remaining underscores with a space and capitalizes the result.

If the second character is not an underscore then no replacement occurs and BEAUTIFY behaves as normal.

View example using BEAUTIFY keyfilter

Either use the view above and modify BEAUTIFY or use a newer BEAUTIFY with a view such as the following

{{extend 'layout.html'}}
<br />
{{=BEAUTIFY(response._vars, keyfilter=lambda key: ' '.join([x.capitalize() for x in key[2:].split('_')]) if key[1:2]=='_' else key)}}

Controller Function Examples

  return dict(cde_fgh='world', ijk_lmn='hello') # Normal behaviour
  cde_fgh: world
  ijk_lmn: hello

  return dict(b_cde_fgh='world', a_ijk_lmn='hello') # Altered behaviour: same keys but order reversed
  Ijk Lmn: hello
  Cde Fgh: world

Web Example

You can see an example of this technique in action at http://www.zgus.com/zgus/products/category_item/1

The view page uses BEAUTIFY with a keyfilter

The last statement of the category_item controller function is

  return stripped_dict(dict(
    d_products= _product_list,

As for the quality of the linked videos in the page, I received a polite complaint from a senior executive of a well known corporation about their poor quality! Their main purpose is to demonstrate I work on further developing real product which is not yet ready to be marketed!

John Heenan

Related slices

Comments (0)

Hosting graciously provided by:
Python Anywhere