Ian Bicking: the old part of his blog


As long as I'm talking about FormEncode, I thought I'd mention htmlfill. htmlfill is an anti-form-generator; it doesn't generate forms at all, but given a bunch of default values and potentially some errors, it'll fill in all the value attributes in your form. This way you can design the form however you want, rearrange things in whatever order, without worrying about form generation rules.

Automatically-generated forms seem cool, especially to programmers, but they don't really work for many public forms, and even for backend administration forms they feel more transitional than essential. Form generators have a terribly time with small exceptions, but small exceptions are the stuff that brings polish to a product, and I don't like putting up a barrier to small tweaks. So I'm inclined towards this technique, given a knowledge of HTML that allows me to fill a form without special templating instructions.

The module doesn't have any dependencies outside of the standard library.

Created 12 Jan '05


Interesting. Can you give an example of how you feed it errors and how they are then displayed?
# anonymous

It's pretty straight forward:

from validator import htmlfill
parser = htmlfill.FillingParser({'lname': 'Doe'}, errors={'fname': 'Please enter a name'})
parser.feed('''<form action="">
<form:error name="fname">
First: <input type="text" name="fname"><br>
<form:error name="lname">
Last: <input type="text" name="lname"><br>''')
print parser.text()

Output (well, slightly reformatted, since it eats newlines right now for some reason):

<form action="">
<span class="error">Please enter a name</span><br>
First: <input type="text" name="fname" value=""><br>
Last: <input type="text" name="lname" value="Doe">

The errors are formatted using htmlfill.default_formatter, or you can use format="formatter_name" to specify your custom formatter. I'd like to include errors by default (if you don't include a specific <form:error> tag), but I haven't figured out how to do that properly; you'd have to double-parse the form, to check which errors were left unused. For now it (optionally) gives you an exception if you include an error without a corresponding <form:error> tag, but this has been problematic.

You can also use <form:iferror name="field_name"> to conditionally include text, in case you need to put a <br> or somesuch into the markup only if you have an error. But for the most part default_formatter (or your custom formatter) is an easier way to put in such tags.

# Ian Bicking

I think the nicest part of form generators is automatic generation of widgets (form controls), which IMHO often have much of business logic that shouldn't be putted into HTML (template), things like size, maxlength etc. Another problem are more advanced / combined widgets (date widget, for example), which require lot's of javascript - I don't want to code them over and over again in every template.

But I agree that the rendering of the form itself needs more freedom - order of the widgets, two widgets on the same line etc. Currently I use Quixote form package with HTMLTemplate (http://freespace.virgin.net/hamish.sanderson/htmltemplate.html), and have the best of both worlds, IMHO :)

# Ksenia

Data-driven Javascript is reasonably easy to use with these techniques; in that model, the Javascript reads and writes to a normal input element (maybe hidden), and is set up separately from the tag. For example, I've used htmlfill with jscalendar with no problem. That kind of Javascript is generally accessible to non-Javascript-supporting browsers too, so it's a good feature anyway.

# Ian Bicking

Yes, I see.... Also sorry for the last comment, I didn't notice that input attributes (size, maxlength etc.) can be passed with add_attributes. I think htmlfill is very usefull right now, but just out of curiosity: do you think it needs some extra functionality? Do you miss something in htmlfill already? :)

# Ksenia

Missing... well, there's the automatic error insertion, which I noted before. It would also be nice if there was a purely information parsing option. Like, you'd be able to put an attribute in like form:required="true" and then parse that out of the form and create a validation schema from that (using whatever validation system you chose). When actually rendering the form, all those attributes would be removed. I think that's mostly it.

# Ian Bicking