Edgewall Software

GenshiRecipes/FormFilling

Version 10 (modified by cmlenz, 8 years ago)

--

Genshi Recipes: Automatically Populating an HTML Form

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.

<html xmlns:py="http://genshi.edgewall.org/">

  <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('@value')" />

  <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>

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'}

Then 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 a template filter

The second, and maybe better, option, would be to use a custom template filter that filled in the form values. An example is attached to this page, and would be used like this:

tmpl = loader.load('myform.html')
fill = HTMLFormFiller({
    'name': 'Look, Ma',
    'enable': 'on',
    'option': 'B',
    'description': 'This is the description someone put in here',
    'dropdown': '2'
})
print tmpl.generate().filter(fill).render('xhtml')

That would result in the same output as above.

Note: the HTMLFormFiller class has been added to the genshi.filters module in [340] and will be included in the upcoming 0.4 release.


See also: GenshiRecipes, Genshi XML Template Language