Genshi Recipes: Automatically Populating an HTML Form
The goal is to automatically add a value attribute to any <input> element with the appropriate data, and similar for other kinds of form controls.
Assume the following template defining a simple form:
<html xmlns:py="http://genshi.edgewall.org/"> <form action="" method="POST"> <!--! A simple text field --> <p> <label>Something: <input type="text" name="name"/></label> </p> <!--! A check box --> <p> <label>Enabled: <input type="checkbox" name="enable" /></label> </p> <!--! A text area --> <p> <label for="description">Description</label> <textarea id="description" name="description">Bla bla bla</textarea> </p> <!--! A radio group --> <fieldset> <legend>Select one:</legend> <label py:for="option in ('A', 'B', 'C')"> <input type="radio" name="option" value="$option" /> </label> </fieldset> <!--! A select box --> <p> <label>Select another: <select name="dropdown"> <option py:for="option in range(1, 4)" value="$option">$option</option> </select> </label> </p> </form> </html>
Using a Stream Filter
The best option is to use the Genshi HTMLFormFiller stream filter that fills in form values.
tmpl = loader.load('myform.html') fill = HTMLFormFiller(data={ 'name': 'Look, Ma', 'enable': 'on', 'option': 'B', 'description': 'This is the description someone put in here', 'dropdown': '2' }) print tmpl.generate().filter(fill).render('html')
The output would look as follows:
<html> <form action="" method="POST"> <p> <label>Something: <input value="Look, Ma" type="text" name="name" /></label> </p> <p> <label>Enabled: <input type="checkbox" name="enable" /></label> </p> <p> <label for="description">Description</label> <textarea id="description" name="description">This is the description someone put in here</textarea> </p> <fieldset> <legend>Select one:</legend> <label> <input type="radio" name="option" value="A" /> </label> <label> <input selected="selected" type="radio" name="option" value="B" /> </label> <label> <input type="radio" name="option" value="C" /> </label> </fieldset> <p> <label>Select another: <select name="dropdown"> <option value="1">1</option> <option selected="selected" value="2">2</option> <option value="3">3</option> </select> </label> </p> </form> </html>
Using Match Templates
The following template provides a match template that automatically adds a value attribute to any <input> element that has matching data in the context.
… <input py:match="form//input[@type='text']" py:attrs="select('@*')" value="${form.get(str(select('@name')))}" /> <input py:match="form//input[@type='checkbox']" py:attrs="select('@*')" checked="${form.get(str(select('@name')))}" /> <input py:match="form//input[@type='radio']" py:attrs="select('@*')" py:with="value = form.get(str(select('@name')))" checked="${value and (value == str(select('@value'))) or None}" /> <textarea py:match="form//textarea" py:attrs="select('@*')" py:content="form.get(str(select('@name')))"></textarea> <select py:match="form//select" py:attrs="select('@*')" py:with="select_name = str(select('@name'))" py:content="select('option|optgroup')" /> <option py:match="form//select//option" py:attrs="select('@*')" py:with="sel_value = form.get(select_name)" selected="${sel_value and (str(select('@value')) == sel_value) or None}" py:content="select('text()')" /> …
Assuming the context data contained a variable “form” that was set to:
form = {'name': 'Look, Ma', 'enable': '', 'option': 'B', 'description': 'This is the description someone put in here', 'dropdown': '2'}
That would result in the same (or similar) output as above.
See also: GenshiRecipes, Genshi XML Template Language