Michele Simionato
I don't thing there is anything "recommended" except personal
recommendations. Personally, I like Hamish Sanderson's HTMLTemplate
(http://freespace.virgin.net/hamish.sanderson/htmltemplate.html), but I
may be biased. ;)
Hamish planned to start process that would lead to inclusion of
HTMLTemplate to standard library, but I don't think it's gonna happen in
any foreseeable future.
--
Jarek Zgoda
http://jpa.berlios.de/ | http://www.zgodowie.org/
> What is the recommended way of generating HTML from Python? I know of
> HTMLGen and of
> few recipes in the Cookbook, but is there something which is more or
> less standard?
I'm also an htmlgen user, but it's getting a bit long in the tooth, and the
installation is not very clean (pre-distutils). I keep an eye out for
alternatives, here's one (which I haven't looked at yet):
######
htmldata 1.0.6 is available.
http://oregonstate.edu/~barnesc/htmldata/
The htmldata module allows one to translate HTML
documents back and forth to list data structures.
This allows for programmatic reading and writing
of HTML documents, with much flexibility.
######
I could swear that I also saw another recent email announcing an htmlgen
alternative, but no amount of googling or digging through my email could turn
it up. I think it was in the last month or so, and probably on the
python-announce list, but looking through the archives I can't find it. Maybe
my memory is playing tricks on me.
> Also, are there plans to include a module for HTML generation in the
> standard library?
> I really would like to see some standardization in this area.
I would too. The HTMLgen model is quite nice and clean (at least for my simple
uses), but I'd use anything, as long as it's included by default and supported.
Cheers,
f
- I posted a 70-line recipe on the Python Cookbook, a sort of poor man's
HTMLGen called HTMLTags
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/366000
with a syntax like this :
# print HTML( HEAD(TITLE('Test document')) +
# BODY(H1('This is a test document')+
# TEXT('First line')+BR()+
# TEXT('Second line')))
The use of addition allows for shortcuts like
print Sum([ TR(TD(i)+TD(i*i)) for i in range(100) ])
where Sum works like the built-in sum, but sum only works for numbers
apparently
- in the Cookbook someone mentioned the HyperText package, published in
2000 by Andy Dustman : http://dustman.net/andy/python/HyperText/
It uses this syntax :
# print TABLE(
# TR((TH('SPAM'), TH('EGGS')),
# TR(TD('foo','bar', colspan=2))
# )
The package also handles XML, SGML etc.
- I wrote to Andy and he said there was also Living Logic's XIST :
http://www.livinglogic.de/Python/xist/index.html
An example taken from the site :
#node = xsc.Frag(
# xml.XML10(),
# html.DocTypeXHTML10transitional(),
# html.html(
# html.head(
# meta.contenttype(),
# html.title("Example page")
# ),
# html.body(
# html.h1("Welcome to the example page"),
# html.p(
# "This example page has a link to the ",
# html.a("Python home page", href="http://www.python.org/"),
# "."
# )
# )
# )
# )
#
# print node.conv().asBytes(encoding="us-ascii")
For example:
class Greeter(rend.Page):
def greet(self, context, data):
return random.choice(["Hello", "Greetings", "Hi"]), " ", data
docFactory = loaders.stan(
tags.html[
tags.head[ tags.title[ "Greetings!" ]],
tags.body[
tags.h1(style="font-size: large")[ "Now I will greet you:" ],
greet
]
])
(From http://nevow.com/releases/0.3.0/nevow-intro.html)
I don't know how detachable it is from the rest of nevow. I'd assume it
wouldn't be too difficult to implement in a standalone fashion.
xtian
FWIW I whipped up a simple self-contained Stan clone a while back:
http://freespace.virgin.net/hamish.sanderson/stanlite.py
It's a bit quick-n-dirty - I think ideally you'd want it to parse all
the HTML element information from a DTD and perform proper validation
of input data - but if anyone want to pick it up and run with it, or
just use it as-is, they're more than welcome to.
HTH
has
FWIW, here is a my version of the recipe (stripped down to the bare
essentials)
.def makeattr(dict_or_list_of_pairs):
. dic = dict(dict_or_list_of_pairs)
. return " ".join("%s=%r" % (k, dic[k]) for k in dic)
.class HTMLTag(object):
. def __getattr__(self, name):
. def tag(value, **attr):
. """value can be a string or a sequence of strings."""
. if hasattr(value, "__iter__"): # is iterable
. value = " ".join(value)
. return "<%s %s>%s</%s>\n" % (name, makeattr(attr), value,
name)
. return tag
# example:
.html = HTMLTag()
.tableheader = ["field1", "field2"]
.tablebody = [["a1", "a2"],
. ["b1", "b2"]]
.html_header = [html.tr(html.th(el) for el in tableheader)]
.html_table = [html.tr(html.td(el) for el in row) for row in tablebody]
.print html.table(html_header + html_table)
Michele Simionato
Why not teach your students to use a template system?
> FWIW, here is a my version of the recipe (stripped down to the bare
> essentials)
>
> .def makeattr(dict_or_list_of_pairs):
> . dic = dict(dict_or_list_of_pairs)
> . return " ".join("%s=%r" % (k, dic[k]) for k in dic)
>
> .class HTMLTag(object):
> . def __getattr__(self, name):
> . def tag(value, **attr):
> . """value can be a string or a sequence of strings."""
> . if hasattr(value, "__iter__"): # is iterable
> . value = " ".join(value)
> . return "<%s %s>%s</%s>\n" % (name, makeattr(attr), value,
> name)
> . return tag
>
> # example:
> .html = HTMLTag()
>
> .tableheader = ["field1", "field2"]
> .tablebody = [["a1", "a2"],
> . ["b1", "b2"]]
>
> .html_header = [html.tr(html.th(el) for el in tableheader)]
> .html_table = [html.tr(html.td(el) for el in row) for row in tablebody]
> .print html.table(html_header + html_table)
*Shudder*
I've written web pages this way (using a pretty nice Java HTML generation package) and I don't
recommend it. In my experience, this approach has several drawbacks:
- as soon as the web page gets at all complex, the conceptual shift from HTML to code and back is
difficult.
- It is hard to work with a designer. The designer will give you sample web pages which then have to
be hand-translated to code. Changes to the web page have to be located in the code.
- There is no separation of content and presentation
IMO templating systems are a much better solution. They let you express HTML in HTML directly; you
communicate with a designer in a language the designer understands; you can separate content and
presentation.
Kent
>
> Michele Simionato
>
Slightly off topic but, just to be clear, Nevow supports XHTML templates
*and* stan tag expressions. Both are useful. As a general rule, I stick
to XHTML templates but I use stan for prototyping pages and when marking
up the XHTML templates gets so complicated that they might as well be
written in Python anyway.
Also, just because the HTML code is not in a .html file does not
necessarily mean that content and presentation are mixed up. For
instance, with stan (and probably the alternatives mentioned in this
thread) it's very easy to build a tag library that the "real" Python
code simply calls on to render page content.
>
> IMO templating systems are a much better solution. They let you express HTML in HTML directly; you
> communicate with a designer in a language the designer understands; you can separate content and
> presentation.
Agreed. Although I would go further and say that it's important to
choose a templating system that allows the Python developer to annotate
XHTML templates using **valid XML**, i.e. no "for x in y" loops, no "if
foo" conditionals, no "i = 0" variable setting, no expression
evaluations, etc.
<advocacy>
The lovely thing about Nevow is that it encourages good separation -
HTML is HTML and logic is Python, as it should be - but does not get in
the way when breaking the rules is necessary or just a lot easier.
</advocacy>
Cheers, Matt
--
__
/ \__ Matt Goodall, Pollenation Internet Ltd
\__/ \ w: http://www.pollenation.net
__/ \__/ e: ma...@pollenation.net
/ \__/ \ t: +44 (0)113 2252500
\__/ \__/
/ \ Any views expressed are my own and do not necessarily
\__/ reflect the views of my employer.
Wouldn't we *all* like all of our problems worked out for us. ;)
> class HTMLTag(object):
> [wonderful code snipped]
That's a reasonable start, and you have some fun magic in there, but I think you're going to hit a wall of complexity Real Soon Now--elements without a separate closing tag, safe attribute quoting, and general usability pressures will start to bite you. I note also what Kent said about separation, and the desire to "hand things off to a web designer".
In my own work, I tried to meet both of these concerns with a single Assembly class, which you can see at http://www.aminus.org/rbre/cation/html/assembly.py. At its most basic, it is nothing more than a namespace plus a template. I think it solves the separation issue nicely by allowing the template to be loaded from a file, whether that file be HTML from a designer, HTML "bulding blocks" which a developer might supply, or even CSS, or an email template. But it also allows for useful subclassing, for code generation. Here's an example: the subclass for "hidden input" elements:
class HiddenElement(Assembly):
"""An Assembly for generating HTML <input type='hidden'> elements
Usage:
output = assembly.HiddenElement(app).assemble_all(key)
"""
templateText = u'<input type="hidden" name=%(name)s value=%(value)s />'
def assemble_all(self, name, value):
return self.assemble({u'name': html.quote(name),
u'value': html.quote(value)})
The "assemble_all" method allows the developer to focus on the important bits (name and value) and forget the implementation details. Check out the TableRows class for a more complex example, whereby an HTML table can be built incrementally, inline with the data access logic.
Now, getting into usability concerns (that framework and library authors tend to obsess over ;) may be too advanced for your class at the moment. But that's why recipes are recipes, not standard library modules: they're often biased toward quick and dirty scripting, not usable, maintainable edifices.
Robert Brewer
MIS
Amor Ministries
fuma...@amor.org
Agreed. Don't use HTML generation simply for the sake of it. While it
has its niche, for most tasks templating is more appropriate. There
aren't any 'blessed' solutions, so just pick whichever third-party
system best fits your needs.
Why does use of a templating system whose documemts are valid XML
imply no loops, conditionals, expression evaluation etc.?
Or are you just talking about particular (non-XML) syntaxes for these
constructs?
John
Yea, why can't we start using xHTML like any other GUI toolkit, its just
a tree of widgets. The layout is completely up to CSS... One could write
Form classes with automatic generation of client(javascript) and
server side(python) validators ;)
greetings
Paul