Edgewall Software

GenshiRecipes/FormFilling

Version 15 (modified by anonymous, 6 years ago)

--

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 Flter

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