Proposal: Better HTML4 support

61 views
Skip to first unread message

Rob Hudson

unread,
Sep 26, 2009, 12:48:35 AM9/26/09
to Django developers
Or: Why is HTML4 such a PITA to get right?

Outline:
* What I know about HTML4 and Django
* Some info about past efforts and discussions
* Thoughts and curiosities about what we can do

What I know about HTML4 and Django
============================

First, let's not let this turn into an argument about HTML vs XHTML.
People have their preference one way or the other, and I believe
Django should be agnostic.

Currently, however, Django *is* biased to producing XHTML output in
the various places that output HTML, such as comments, formtools,
csrf, forms.widgets, and various filters and HTML utilities that
output "<br />" tags. For someone that prefers an HTML4 doctype, this
is a hassle with no easy answer.

Some info about past efforts and discussions
=================================

Some tickets already open on this...

Ticket #6925: CSRF html output is not valid html (it is xhtml)
http://code.djangoproject.com/ticket/6925

Ticket #7281: Add doctype tag to webdesign template tags
http://code.djangoproject.com/ticket/7281

Ticket #7452: Settings for HTML4 or XHTML output
http://code.djangoproject.com/ticket/7452

Proposal from Mar 2008:
Form rendering with filters...
http://groups.google.com/group/django-developers/browse_thread/thread/5f3694b8a19fb9a1

Proposal from Sept 2008:
{% doctype %} and {% field %} tag for outputting form widgets as HTML
or XHTML...
http://groups.google.com/group/django-developers/browse_thread/thread/f04aed2bc60274f0

Since those tickets aren't closed as "wontfix" or "invalid", and much
of the conversation surrounding this agrees that *something* should be
done, I'm hoping to start a conversation as to what that something
might be.

Thoughts and curiosities about what we can do
==================================

After thinking for some time, I've only been able to come up with two ideas...

1. Incorporate something along the lines of Simon's django-html
project (http://github.com/simonw/django-html).

I think the genera idea is this: You set a doctype in your base
template via a template tag (e.g. {% doctype "html4" %}, and any
rendering that is done after that (in inherited or included templates)
is based on this doctype.

Advantages:
* It puts the doctype decision into the hands of the designer.
* It allows for different parts of an application to have different doctypes.

Shortcomings:
* Fixes the symptom, not the bug. [1] I think the fix should not do
string replacement, but output the correct HTML in the first place.
(I realize this is the best one can hope for as a 3rd party app, but
if something were to come into core it would have the ability to fix
things properly.)
* Doesn't "fix" the rest of the areas where Django outputs XHTML. Is
it possible?
* Ties various parts of Django to the-thing-that-produces-HTML.

2. Add a new setting, e.g. settings.DOCTYPE, that various parts of
Django and 3rd party apps use to render HTML.

Advantages:
* Simple and straightforward

Shortcomings:
* Yet another setting
* Doesn't allow for template level decisions of doctype by designers


Since I think idea #1 has the best chance of making headway, I've
tried to look at how it might be done. Unfortunately, I don't know
the template system well enough to see how setting {% doctype "html4"
%} might be able to affect other areas of Django. Here was my thought
process the other night...

If Django widgets and other parts of Django always used the Template
system to render HTML, it might be possible to set some global context
variable of the current doctype. But perhaps the reason for not doing
this initially is because each `get_template` call results in a read
from the filesystem (or thread safety?)? In which case, we should
consider fixing #6262, Cache templates. Using Templates everywhere
does inhibit re-use of pieces of Django outside of Django as they
would all now rely on Django's templates.

There's also the option of something like Werkzeug's HTMLBuilder[2]
and their use in Solace widgets[3].

I don't claim to have the answer, but I'm willing to put time and
effort into helping solve this. Thoughts? Other ideas?

Thanks,
Rob

[1] http://www.pointy-stick.com/blog/2007/09/04/fix-bug-not-symptom/
[2] http://dev.pocoo.org/projects/werkzeug/browser/werkzeug/utils.py#L126
[3] http://bitbucket.org/plurk/solace/src/tip/solace/utils/forms.py#cl-294

Jerome Leclanche

unread,
Sep 26, 2009, 1:50:11 AM9/26/09
to django-d...@googlegroups.com
This is a non-issue.

Correct me if I'm wrong, but <br /> is valid html syntax. It's parsed
as valid by every html parser, and I'm positive this is the entire
point of xhtml: staying backwards-compatible with html.

J. Leclanche / Adys

Jerome Leclanche

unread,
Sep 26, 2009, 1:53:38 AM9/26/09
to django-d...@googlegroups.com
Mail fired a bit early there.

That said, I'm not against a {% doctype %} tag or anything. However, I
do think having an xhtml default is a Good Thing due to its backwards
compatibility. I'm also not entirely fond of the idea of having 100
different language outputs in Django. Why stop only after xhtml and
html? So on.
I'm all for a better abstraction, but it needs to be thought twice
before adding features "just because".

J. Leclanche / Adys

Simon Willison

unread,
Sep 26, 2009, 4:56:08 AM9/26/09
to Django developers
On Sep 26, 6:50 am, Jerome Leclanche <adys...@gmail.com> wrote:
> This is a non-issue.

<personal opinions follow>

Obviously I disagree - this is a tiny thing that has bugged me ever
since newforms. It's also something I find myself constantly
apologising to front-end developers about, who for the most part love
the Django template language.

After 9 years In the marketplace, I think XHTML has pretty much lost.
It turns out that XML serialisations of HTML aren't nearly as useful
as people thought they would be (running an XML parser against the web
won't get you anywhere fast, and there are plenty of excellent HTML
parsing libraries now), and strict XML error handling is completely
unsuitable for the practical considerations of the web. HTML 5 is the
final nail in the coffin - the refocusing of the W3C on that over
XHTML 2 is an acknowledgement that XML is no longer the future of the
Web. I actually think Django's XHTML output makes us look a bit out of
date.

> Correct me if I'm wrong, but <br /> is valid html syntax. It's parsed
> as valid by every html parser, and I'm positive this is the entire
> point of xhtml: staying backwards-compatible with html.

If you want backwards compatibility you need HTML 5, not XHTML.

HTML 5 is backwards compatible - it even goes as far as specifying the
error handling routines that browsers should take when faced with
invalid code (routines that have been reverse-engineered from existing
browsers) and properly specifying all of the APIs that browsers
support but were never actually part of a specification, such as
XMLHttpRequest and innerHTML.

XHTML 1.0 is kind-of backwards compatible, but it's a bit of a fudge.
It's really meant as a transitional stage between HTML 4 and the
stricter XHTML 1.1. As an example of a fudge, the <br /> self-closing
tags actually mean something different in SGML (HTML's parent
language) - they're a short-hand feature called Null End Tags which
should technically result in extra > signs appearing in the text, but
thankfully no browser actually supports enough of SGML for that to be
a problem.

The moment you start serving XHTML with the correct content-type
(application/xml+html) all sorts of nasty things happen - in addition
to strict error handling the way the JavaScript DOM works
fundamentally changes - document.getElementsByTagName becomes
getElementsByTagNameNS for example.

XHTML 1.1 backwards incompatible - the spec forbids the use of the
text/html content-type and insists on application/xhtml+xml or
application/xml, which breaks completely in IE and causes other
browsers to use strict error handling (which you really, really don't
want).

XHTML 2.0 was completely backwards incompatible (tags were removed,
new incompatible tags added), a major factor in the W3C ending
official work on it.

> That said, I'm not against a {% doctype %} tag or anything. However, I
> do think having an xhtml default is a Good Thing due to its backwards
> compatibility.

I see XHTML as a dead end, so I'd personally prefer to switch to an
HTML 5 default - but the {% doctype %} thing makes switching to HTML 5
painless enough that I wouldn't mind the existing XHTML behaviour
remaining as the default (purely to avoid causing issues with existing
applications).

> I'm also not entirely fond of the idea of having 100
> different language outputs in Django. Why stop only after xhtml and
> html?

Because Django is a Web framework, and XHTML and HTML are the key web
languages. I don't think we need to worry about support for those two
leading to a slippery slope.

Cheers,

Simon

Simon Willison

unread,
Sep 26, 2009, 5:13:35 AM9/26/09
to Django developers
On Sep 26, 5:48 am, Rob Hudson <treborhud...@gmail.com> wrote:
> First, let's not let this turn into an argument about HTML vs XHTML.

Oops, sorry!

> People have their preference one way or the other, and I believe
> Django should be agnostic.

Completely agree - that's why I'm in favour of a Django doctype switch
rather than a fullscale switch to HTML 5.

> django-html Shortcomings:
> * Fixes the symptom, not the bug. [1] I think the fix should not do
> string replacement, but output the correct HTML in the first place.
> (I realize this is the best one can hope for as a 3rd party app, but
> if something were to come into core it would have the ability to fix
> things properly.)

Yes - I looked briefly at how much work was involved in doing this and
it's not insubstantial, which is why I opted for string replacement
just to demonstrate the API. I'm confident the exact functionality of
django-html could be replicated in a less messy way by patching core,
but it would require quite a bit of refactoring of django.forms.

> * Doesn't "fix" the rest of the areas where Django outputs XHTML. Is
> it possible?

I think the key problem is template filters, which often produce XHTML
(linebreaksbr for example). This could be solved by allowing template
filters selective access to the template context, which I'm in favour
of in the absence of a compelling argument against. This could be done
in a way that allows existing filters to continue to work - maybe
something as simple as this:

register.filter('cut', cut, takes_context=True)

Which emulates the register.inclusion_tag API.

> 2. Add a new setting, e.g. settings.DOCTYPE, that various parts of
> Django and 3rd party apps use to render HTML.
>
> Advantages:
> * Simple and straightforward
>
> Shortcomings:
> * Yet another setting
> * Doesn't allow for template level decisions of doctype by designers

Really not keen on that - designers should be able to pick their
doctype, and there are some cases where specific pages of a site (or
of a reusable app) might need to use a specific doctype - MathML
output still requires XHTML for example.

I've somewhat foolishly volunteered for a bunch of 1.2 related hacking
already (CSRF, logging, signing) but I remain actively interested in
this, so I'll try to keep an eye on things and see if there's anything
I can contribute.

Cheers,

Simon

Max Battcher

unread,
Sep 26, 2009, 5:17:57 AM9/26/09
to django-d...@googlegroups.com
Simon Willison wrote:
> HTML 5 is the
> final nail in the coffin - the refocusing of the W3C on that over
> XHTML 2 is an acknowledgement that XML is no longer the future of the
> Web. I actually think Django's XHTML output makes us look a bit out of
> date.

I don't think either of those conclusions can be drawn from the facts.
XHTML 2 was a bold attempt to redefine what it is exactly that web pages
produce: less crud, more content. I'm, personally, a bit disappointed
that it has been "canceled", but I assume that smart people will
continue to explore concepts in that direction.

XHTML 2's cancellation does not say that XHTML 1 was a bad idea or is in
anyway invalidated and it absolutely says nothing about XML. (Also,
whether or not XML is the "future" of the web, it is a strong part of
what defines the "present".)

Furthermore, support for XHTML "5" (which is indeed a part of the HTML 5
standard) shows that XHTML 1's principles are still around and still
respected. Django's XHTML output can't be "out of date" if XHTML 5 is
considered a successor to XHTML 1.

--
--Max Battcher--
http://worldmaker.net

Simon Willison

unread,
Sep 26, 2009, 6:19:13 AM9/26/09
to Django developers
On Sep 26, 10:17 am, Max Battcher <m...@worldmaker.net> wrote:
> Furthermore, support for XHTML "5" (which is indeed a part of the HTML 5
> standard) shows that XHTML 1's principles are still around and still
> respected. Django's XHTML output can't be "out of date" if XHTML 5 is
> considered a successor to XHTML 1.

Opinions differ, but in the interest of keeping this thread about HTML
support in Django I'm going to leave that discussion here - let's
assume that it would be a Good Thing for Django should provide support
for outputting both HTML and XHTML, and focus on how we can achieve
that.

Cheers,

Simon

SeanOC

unread,
Sep 26, 2009, 10:15:03 AM9/26/09
to Django developers
Another fun wrinkle to think about in this discussion is third-party
apps. Currently there are numerous useful apps out there which you
can't really use if you want to have HTML(5) output because they have
XHTML output hard-coded. The developers of these apps haven't done a
"bad" thing here, they simply mirrored Django's own behavior.

As an interim solution I've forked django-html (http://github.com/
SeanOC/django-html) and added a middleware which does the XHTML=>HTML
string replacement. This is obviously a fairly messy approach but it
is the only way I've figured out to work with third party apps without
maintaining HTML compatible forks of everything.

To address this problem the "right" way, I'd suggest that in addition
to fixing Django's own HTML output to respect a {% doctype %} tag, we
should also provide tools to make it easy for developers to respect
that tag. I'm not sure what form those tools should take right now
but it's definitely something that should be consider as part of the
solution to this problem.

Rob Hudson

unread,
Sep 26, 2009, 1:34:16 PM9/26/09
to django-d...@googlegroups.com
On Sat, Sep 26, 2009 at 2:13 AM, Simon Willison <si...@simonwillison.net> wrote:
> Yes - I looked briefly at how much work was involved in doing this and
> it's not insubstantial, which is why I opted for string replacement
> just to demonstrate the API. I'm confident the exact functionality of
> django-html could be replicated in a less messy way by patching core,
> but it would require quite a bit of refactoring of django.forms.

This is the bit I was hoping we could get to. What would that
refactoring look like, you think? Would it involve making forms use
Templates? Or something else?

> I think the key problem is template filters, which often produce XHTML
> (linebreaksbr for example). This could be solved by allowing template
> filters selective access to the template context, which I'm in favour
> of in the absence of a compelling argument against. This could be done
> in a way that allows existing filters to continue to work - maybe
> something as simple as this:
>
> register.filter('cut', cut, takes_context=True)
>
> Which emulates the register.inclusion_tag API.

We've got django.forms and tags/filters on the plate. How might we
fix something like comments which has templates which write out XHTML
(or other little places which hand code HTML)?

For example, if one includes contrib.comments in their HTML4 website,
it doesn't validate...
http://validator.w3.org/check?uri=http%3A%2F%2Fjacobian.org%2Fwriting%2Fsnakes-on-the-web%2F&charset=%28detect+automatically%29&doctype=Inline&group=0

Ahem. Sorry Jacob!

I'd really hate to see something like this everywhere:

<input type="hidden" name="next" value="{{ next }}"{% if
doctype.xhtml %} /{% endif %}>

> Really not keen on that - designers should be able to pick their
> doctype, and there are some cases where specific pages of a site (or
> of a reusable app) might need to use a specific doctype - MathML
> output still requires XHTML for example.

I agree.

Simon mentioned how HTML and XHTML could result in Javascript and DOM
differences -- should we be concerned about being too dynamic about
swapping out HTML for XHTML, and vice versa, for fear of breaking
Javascript and CSS that rely on them?

For example, I think the Django admin is fine as XHTML since it isn't
intended to be an included part of your website. But say we were able
to easily set a different doctype that rendered as HTML4. Does that
have the possibility of really breaking things?

> I've somewhat foolishly volunteered for a bunch of 1.2 related hacking
> already (CSRF, logging, signing) but I remain actively interested in
> this, so I'll try to keep an eye on things and see if there's anything
> I can contribute.

If we can come up with something that everyone is happy with, I'm in
for volunteering time to help code it. I'm sure it will be a learning
experience for me as far as Django internals, but I'm willing to put
the effort into it.

Thanks,
Rob

Simon Willison

unread,
Sep 26, 2009, 2:33:36 PM9/26/09
to Django developers
On Sep 26, 6:34 pm, Rob Hudson <treborhud...@gmail.com> wrote:
> This is the bit I was hoping we could get to.  What would that
> refactoring look like, you think?  Would it involve making forms use
> Templates?  Or something else?

I don't think it would involve form widgets being rendered with
templates simply because of the performance overhead - even with the
template caching improvements it's still a lot of work just to output
an input tag. It might involve some kind of light-weight helper for
outputting tags though - render_tag('input', {'type': 'text', 'name':
'blah'}, xhtml=True) maybe.

The form.as_p stuff works as either HTML or XHTML. It would be nice to
further emphasise the ease with which people can create their own
reusable form templates (define them as an includable fragment that
iterates over the form), and it would be nice if there were more
finely grained methods for things like accessing the HTML ID of a form
field. I don't see any reason to templatise those parts in particular
though - unless someone has smart ideas about how baked in default
templates could dramatically improve the overall form experience.

> We've got django.forms and tags/filters on the plate.  How might we
> fix something like comments which has templates which write out XHTML
> (or other little places which hand code HTML)?

That's tricky. There are really only a few tags that actually differ -
anything that needs to be self closing, which means the following:

<area />
<base />
<basefont />
<br />
<hr />
<input />
<img />
<link />
<meta />

Of these, only meta, link, img, input and br are really common. I can
think of a few ways of dealing with this, none of them particularly
enticing:

1. a {% selfclose %} template tag:

<br{% selfclose %}>

{% selfclose %} outputs either blank or " /" depending on the doctype.

2. a {% tag %} tag:

{% tag br %}

Like the {% field %} tag, this could take optional attributes:

{% tag br class="break" %}

3. {% field %} style tags for all of the self-closing XHTML tags:

{% br %} {% br class="break" %}
{% hr %}
{% meta name="dc:author" value="Simon" %}

This option really sucks - that's 9 new template tags polluting our
default template namespace which do almost nothing. That said, if we
added template tag namespacing we could at least do {% tag.br %}, {%
tag.hr %} etc.

They're all pretty horrible, but I think out of those I prefer option
1 (maybe with a better, shorter name).

> For example, I think the Django admin is fine as XHTML since it isn't
> intended to be an included part of your website.  But say we were able
> to easily set a different doctype that rendered as HTML4.  Does that
> have the possibility of really breaking things?

The JavaScript differences only come up when you start serving stuff
as application/xml+xhtml, which I would strongly suggest we avoid
doing at all costs (hence the need to stick the admin with XHTML 1.0
and avoid ever upgrading to 1.1). I'm not worried about that aspect.

Cheers,

Simon

veena

unread,
Sep 27, 2009, 5:49:03 AM9/27/09
to Django developers
Hi all,

my bits to discussion about supporting various (X)HTML versions.

1) Problem with (X)HTML in python code (in applications)
I discovered this python package http://pypi.python.org/pypi/html/1.6
It allows you to write "python like HTML syntax" and generates HTML or
XHTML.

2) Problem with (X)HTML in templates
I think there should be parser, which parse template just before
caching templates. Code could be messy HTML or (XHTML) or invalid HTML
(like undisclosed tags, attributes without quotations marks etc.) and
from this make pretty HTML or XHTML according to html coder settings
by {% doctype %}

The template post processing also enables to make code nicer indented
or flatten. Or even use as templating language something like REST,
textile etc.

The python packages that could be involved in parsing messy (X)HTML
and I know about them:
http://pypi.python.org/pypi/BeautifulSoup/3.0.7a
http://pypi.python.org/pypi/html5lib/0.10


Best,
Vaclav

Simon Willison

unread,
Sep 27, 2009, 7:46:43 AM9/27/09
to Django developers
On Sep 27, 10:49 am, veena <vsto...@gmail.com> wrote:
> my bits to discussion about supporting various (X)HTML versions.
>
> 1) Problem with (X)HTML in python code (in applications)
> I discovered this python packagehttp://pypi.python.org/pypi/html/1.6
> It allows you to write "python like HTML syntax" and generates HTML or
> XHTML.

Something like that might be an option for cleaning up the way markup
is generated within the forms framework itself, but ultimately I think
adding an entirely new Python-based generation method just to output a
few strings wouldn't be worth the added dependency.

> 2) Problem with (X)HTML in templates
> I think there should be parser, which parse template just before
> caching templates. Code could be messy HTML or (XHTML) or invalid HTML
> (like undisclosed tags, attributes without quotations marks etc.) and
> from this make pretty HTML or XHTML according to html coder settings
> by {% doctype %}

The performance overhead rules out this kind of approach for Django
core - any post-processing run against the output of the templates
would be executed on every single Django request, and HTML parsing and
rewriting is a very expensive operation. That's not to say a third
party module couldn't be written to do this kind of thing for people
who really want to clean up their output (I remember there being an
HTMLTidy middleware a few years back that did this) but it wouldn't be
suitable for inclusion in core.

Cheers,

Simon

Andreas

unread,
Sep 28, 2009, 5:12:24 AM9/28/09
to Django developers
html4 is derecated.
xhtml is deprecated.


With google chrome frame out there theres absolutly no reason to not
begin with html5 already.
The longer we wait, the longer it will take before html5 becomes "the
it".

</rant>

Jerome Leclanche

unread,
Sep 28, 2009, 5:18:59 AM9/28/09
to django-d...@googlegroups.com
This is unrelated Andreas. HTML5 has the exact same syntax as HTML4,
just new tags.
This thread is about syntax.

By the way, neither html4 nor xhtml are deprecated. HTML5 is still not
"officially released".
J. Leclanche / Adys

Russell Keith-Magee

unread,
Sep 28, 2009, 9:38:03 AM9/28/09
to django-d...@googlegroups.com
On Sun, Sep 27, 2009 at 1:34 AM, Rob Hudson <trebor...@gmail.com> wrote:
>
> On Sat, Sep 26, 2009 at 2:13 AM, Simon Willison <si...@simonwillison.net> wrote:
>> Yes - I looked briefly at how much work was involved in doing this and
>> it's not insubstantial, which is why I opted for string replacement
>> just to demonstrate the API. I'm confident the exact functionality of
>> django-html could be replicated in a less messy way by patching core,
>> but it would require quite a bit of refactoring of django.forms.
>
> This is the bit I was hoping we could get to.  What would that
> refactoring look like, you think?  Would it involve making forms use
> Templates?  Or something else?

This is idea that I think has a lot of merit. Django has always had a
policy of being client-side agnostic - the XHTML-specific output
format has always been the chink in that armor. The impending
significance of HTML5 increases the incentive to have this debate (and
more importantly, to get it right).

If this requires changes to the way forms and fields are rendered, I'm
happy to entertain those ideas, as long as they retain backwards
compatibility.

However, as with the signed cookie discussion, I don't have any
particularly strong opinions on the exact form that the API should
take, so I will stay out of the discussion and let the community
evolve the idea.

By way of greasing the wheels towards trunk: if the outcome of this
mailing list thread was a wiki page that digested all the ideas,
concerns and issues into a single page, it will make the final
approval process much easier. Luke Plant's wiki page on the proposed
CSRF changes [1] is a good model to follow here - I wasn't involved in
the early stages of that discussion, but thanks to that wiki page, I
was able to come up to speed very quickly and see why certain ideas
were rejected.

[1] http://code.djangoproject.com/wiki/CsrfProtection

Yours,
Russ Magee %-)

Max Battcher

unread,
Sep 28, 2009, 12:20:59 PM9/28/09
to django-d...@googlegroups.com

But I'm not sure that is a correct assertion. I don't think there is a
strong enough difference between HTML and the XHTML that Django
generates for there to be a need for more complicated mechanisms of
rendering. If the only point of contention is self-closing tags (<tag
/>), then HTML 4 might not support it explicitly (although in fact most
modern browsers support it implicitly), but HTML 5 (the HTML form
factor, not just XHTML 5) explicitly supports self-closing tags:

http://dev.w3.org/html5/spec/Overview.html#start-tags

Under Section 9.1.2.1 -- Start Tags, I quote:

6. Then, if the element is one of the void elements, or if the
element is a foreign element, then there may be a single U+002F SOLIDUS
(/) character. This character has no effect on void elements, but on
foreign elements it marks the start tag as self-closing.

I really don't see what the fuss here is about. If we are worried about
forwards-compatibility, HTML 5 takes care of it. If we are worried about
better backwards-compatibility with HTML 4, everyone else is saying that
the future is now and the focus should be HTML 5...

What is this argument really about?

Rob Hudson

unread,
Sep 28, 2009, 1:57:51 PM9/28/09
to django-d...@googlegroups.com
On Sat, Sep 26, 2009 at 11:33 AM, Simon Willison
<si...@simonwillison.net> wrote:
> I don't think it would involve form widgets being rendered with
> templates simply because of the performance overhead - even with the
> template caching improvements it's still a lot of work just to output
> an input tag. It might involve some kind of light-weight helper for
> outputting tags though - render_tag('input', {'type': 'text', 'name':
> 'blah'}, xhtml=True) maybe.

For lack of knowing about anything better, I keep falling back to
Werkzeug's HTMLBuilder class[1]. Pulled out and stripped of comments,
it weighs in at 77 lines of code...

Here's a brief Python shell of how it works...

>>> html = HTMLBuilder('html')
>>> html.input(type='text', name='blah', value='"Quote & Ampersand"')
u'<input type="text" name="blah" value="&quot;Quote &amp; Ampersand&quot;">'
>>> html.select(name='template', id='id_template', *[html.option(v, value=k) for k, v in dict({1: 'One', 2: 'Two', 3: 'Three'}).iteritems()])
u'<select id="id_template" name="template"><option
value="1">One</option><option value="2">Two</option><option
value="3">Three</option></select>'

I really like how it handles children nicely, as in the select/option
example above.

>>> xhtml = HTMLBuilder('xhtml') # XHTML dialect
>>> xhtml.input(type='text', name='blah', value='"Quote & Ampersand"')
u'<input type="text" name="blah" value="&quot;Quote &amp; Ampersand&quot;" />'

This automatic CDATA escaping in XHTML is also nice:

>>> html.script('var id=document.getElementById("id")')
u'<script>var id=document.getElementById("id")</script>'
>>> xhtml.script('var id=document.getElementById("id")')
u'<script>/*<![CDATA[*/var id=document.getElementById("id")/*]]>*/</script>'

I could see using something like this and making a template tag
wrapper around it like the namespace template tag you mention below.
I *think* that would simplify a lot of what you see in the Django
template widget render code that deals with attributes (e.g.
buildattrs, flattatt), which should make writing widgets and
sublcassing widgets a bit easier.

> The form.as_p stuff works as either HTML or XHTML. It would be nice to
> further emphasise the ease with which people can create their own
> reusable form templates (define them as an includable fragment that
> iterates over the form), and it would be nice if there were more
> finely grained methods for things like accessing the HTML ID of a form
> field. I don't see any reason to templatise those parts in particular
> though - unless someone has smart ideas about how baked in default
> templates could dramatically improve the overall form experience.

I agree with what I think I'm reading here -- a goal being to give
designers more fine grained control over the form and form elements at
the template level.

> That's tricky. There are really only a few tags that actually differ -
> anything that needs to be self closing, which means the following:
>
> <area />
> <base />
> <basefont />
> <br />
> <hr />
> <input />
> <img />
> <link />
> <meta />

Also:

<col />
<frame />
<param />

> Of these, only meta, link, img, input and br are really common. I can
> think of a few ways of dealing with this, none of them particularly
> enticing:
>
> 1. a {% selfclose %} template tag:
>
>    <br{% selfclose %}>
>
> {% selfclose %} outputs either blank or " /" depending on the doctype.
>
> 2. a {% tag %} tag:
>
>    {% tag br %}
>
> Like the {% field %} tag, this could take optional attributes:
>
>    {% tag br class="break" %}
>
> 3. {% field %} style tags for all of the self-closing XHTML tags:
>
> {% br %} {% br class="break" %}
> {% hr %}
> {% meta name="dc:author" value="Simon" %}
>
> This option really sucks - that's 9 new template tags polluting our
> default template namespace which do almost nothing. That said, if we
> added template tag namespacing we could at least do {% tag.br %}, {%
> tag.hr %} etc.
>
> They're all pretty horrible, but I think out of those I prefer option
> 1 (maybe with a better, shorter name).

I think you might want both 1 and 3. (1) for those that want finer
control or just don't want to use the underlying HTML wrapper, and (3)
for those that do.

Would it be something to consider adding special case tag, like
comments, to represent the self closing slash depending on current
context's doctype? For example, something like {% / %}?

[1] http://dev.pocoo.org/projects/werkzeug/browser/werkzeug/utils.py#L126

I feel like I'm starting to get a picture in mind for all the pieces
at play here.

Thanks,
Rob

Simon Willison

unread,
Sep 28, 2009, 2:02:44 PM9/28/09
to Django developers
On Sep 28, 5:20 pm, Max Battcher <m...@worldmaker.net> wrote:
> I really don't see what the fuss here is about. If we are worried about
> forwards-compatibility, HTML 5 takes care of it. If we are worried about
> better backwards-compatibility with HTML 4, everyone else is saying that
> the future is now and the focus should be HTML 5...
>
> What is this argument really about?

http://www.djangoproject.com/ calls Django the web framework for
"perfectionists with deadlines". This is a perfectionist issue.

If the problem was incredibly hard to solve or involved breaking
backwards compatibility I'd drop this, but I don't think it's a
particularly big or difficult change. The django-html approach even
gives us a useful extra feature - it allows template developers to add
new attributes to form widgets without needing changes made to the
underlying Python form definitions:

{% field form.name class="foo" onfocus="bar()" %}

It's not just me that gets annoyed by this - when I'm teaching Django
to client-side engineers this tends to come up a lot - and I find the
answer a bit embarrassing. It's basically the only place in Django
that the template author can't control the markup, and good client-
side engineers are pretty picky.

Cheers,

Simon

Simon Willison

unread,
Sep 28, 2009, 2:05:17 PM9/28/09
to Django developers
On Sep 26, 7:33 pm, Simon Willison <si...@simonwillison.net> wrote:
> 1. a {% selfclose %} template tag:
>
>     <br{% selfclose %}>
>
> {% selfclose %} outputs either blank or " /" depending on the doctype.

I've added an experimental {% slash %} tag to django-html to address
the reusable XHTML/HTML templates problem. It's actually not as
horrible as I first thought - you end up writing template code like
this:

<br{% slash %}>

<img src="/site/logo.png" alt="My site"{% slash %}>

It's not exactly beautiful, but it's the simplest thing that could
possibly work. Most Django developers who aren't writing code designed
to be used with differing doctypes won't ever have to use it. In the
absence of a better idea I'm pretty happy with it.

http://github.com/simonw/django-html

Cheers,

Simon

Rob Hudson

unread,
Sep 28, 2009, 2:10:19 PM9/28/09
to django-d...@googlegroups.com
On Mon, Sep 28, 2009 at 6:38 AM, Russell Keith-Magee
<freakb...@gmail.com> wrote:
> By way of greasing the wheels towards trunk: if the outcome of this
> mailing list thread was a wiki page that digested all the ideas,
> concerns and issues into a single page, it will make the final
> approval process much easier. Luke Plant's wiki page on the proposed
> CSRF changes [1] is a good model to follow here - I wasn't involved in
> the early stages of that discussion, but thanks to that wiki page, I
> was able to come up to speed very quickly and see why certain ideas
> were rejected.
>
> [1] http://code.djangoproject.com/wiki/CsrfProtection

I don't mind trying to piece a Wiki page together documenting the
current conversation. I agree it will make a good pointer for
reference and future discussions.

-Rob

Simon Willison

unread,
Sep 28, 2009, 2:32:58 PM9/28/09
to Django developers
On Sep 28, 6:57 pm, Rob Hudson <treborhud...@gmail.com> wrote:
> For lack of knowing about anything better, I keep falling back to
> Werkzeug's HTMLBuilder class[1].  Pulled out and stripped of comments,
> it weighs in at 77 lines of code...

That's not so bad. I was worried about pulling in a large dependency,
but 77 lines (probably dropped in to django.utils.builder or similar)
isn't particularly alarming. I'm still a bit sceptical of introducing
another markup abstraction just to solve this one problem. I wonder if
it could be used to tackle the RSS/Atom generation problem as well?

> I agree with what I think I'm reading here -- a goal being to give
> designers more fine grained control over the form and form elements at
> the template level.

Yes, that's exactly it. Designers should be able to do anything they
like with forms at the template level (hence the {% field form.name
class="foo" %} suggestion). Again, this makes me slightly cautious
about the HTMLBuilder approach since exposing that at the template
level is virtually impossible.

> I think you might want both 1 and 3.  (1) for those that want finer
> control or just don't want to use the underlying HTML wrapper, and (3)
> for those that do.
>
> Would it be something to consider adding special case tag, like
> comments, to represent the self closing slash depending on current
> context's doctype?  For example, something like {% / %}?

I'm really not in favour of 3. 1 I think is OK - as I mentioned above,
I added it to django-html as {% slash %} and it's actually not that
unpleasant. I think I'd rather avoid adding custom syntax like {% / %}
just to support this one tiny edge case (I strongly expect most Django
developers won't ever want to write code that's doctype agnostic - and
as Max mentioned, HTML5 grandfathers in the /> syntax - the tag will
be used strictly by perfectionists).

Cheers,

Simon
Reply all
Reply to author
Forward
0 new messages