James Gardner: Home > Blog > 2007 > Re-Using Fields in a Pylons, Mako...

Re-Using Fields in a Pylons, Mako and FormEncode Workflow

Posted:2007-09-19 22:59
Tags:Pylons, Python, Web, Mako

In most of my Pylons apps nowadays I make use of a few tricks form handling tricks that allow me to re-use the same fields template for creating new objects and updating existing ones. Here's how it works.

First of all I write a Mako template with the fields fragments called fields_fragment.mako:

## -*- coding: utf-8 -*-
<p>
    <label for="approvalgranted">Date Approval Granted<br /></label>
    <input type="text" name="approvalgranted" />
</p>
<p>
    <label for="note">Note<br /></label>
    <input type="text" name="note" />
</p>
<p>
    <label for="enteredby">Last edited by<br /></label>
    <input type=unknown name="enteredby" />
</p>

Then I create two templates to use the fields, one for adding a record, the other for updating it. Here is add.mako:

## -*- coding: utf-8 -*-
<%inherit file="/base/index.mako" />
<%namespace file="fields_fragment.mako" name="fields" import="*"/>
<!% import formencode.htmlfill %>

<h2>Add Requirement</h2>

${h.form(h.url(controller='studyapprovals', action='add', study_id=c.study_id), method='post')}
    ${formencode.htmlfill.render(capture(fields.body), c.values, c.errors)}
    <p><input type="submit" value="Add &raquo;" name="go" class="button" /></p>
${h.end_form()}

and update.mako:

## -*- coding: utf-8 -*-
<%inherit file="/base/index.mako" />
<%namespace file="fields_fragment.mako" name="fields" import="*"/>
<!% import formencode.htmlfill %>

<h2>Update Requirement</h2>

${h.form(h.url(controller='studyapprovals', action='edit', id=c.id,  study_id=c.study_id), method='post')}
     ${formencode.htmlfill.render(capture(fields.body), c.values, c.errors)}
    <p><input type="submit" value="Save" name="go" class="button" /></p>
${h.end_form()}

Notice the lines with ## -*- coding: utf-8 -*- specify the files are encoded with the UTF-8 chracterset which means I can use any Unicode characters I like in the templates. Also notice that both templates inherit from a file /base/index.mako which provides the bulk of the HTML for the page.

The important parts to draw your attention to are the lines:

<%namespace file="fields_fragment.mako" name="fields" import="*"/>

and:

${formencode.htmlfill.render(capture(fields.body), c.values, c.errors)}

The first is effectively an import of the shared fields_fragment.mako file as the namespace fields. I can then output the contents of that file by writing ${fields.body()} in the template to render the body of the fields_fragment.mako template but most of the time that's not what I want to do.

Working with forms is mainly about handling the validation and then repopulating the form with the entered values and error messages. My controllers handle the validation and set c.values and c.errors so I can use formencode.htmlfill to populate the forms. The only complication is that in order to pass the value of calling fields.body() capture the render() function I have to capture it, calling it simply renders the output directly which isn't what I'm after. This is why the call to capture is made.

Comments

Aaron Spike

Posted:

2007-11-02 22:56

confused me at first until I confirmed in the Mako documentation (http://www.makotemplates.org/docs/syntax.html#syntax_python_module-level) that it should be . The initial punctuation is transposed. Thank you for the examples you are providing with this blog. They have been helping me tons!

URL:

http://www.ekips.org

Daniel Pronych

Posted:2007-11-29 22:04

James,

Based on your example, how would you modify the format to allow more than one note to be added/updated at the same time and still provide error handling?

Also, for this example no ID column is maintained, how would you modify add.mako to not require said ID column, while update.mako would require it for a successful update?

Thanks for this example.

URL:http://daniel.dlitz.net

(view source)

James Gardner: Home > Blog > 2007 > Re-Using Fields in a Pylons, Mako...