Allowing multiple {% block %}s in one template

6,431 views
Skip to first unread message

Noam

unread,
Jun 7, 2007, 3:46:05 PM6/7/07
to Django developers
Hello,

I'm in the process of moving from turbogears to django, and I must say
that it looks very nice. Thanks!

Now to my problem and my suggestion.

I want every page in my site to have a title. I want the title to
appear both in the browser title and in the page itself. An example of
the HTML I want is this:

<html>
<head><title>Bug System - Report a New Bug</title></head>
<body>
<h1>Report a New Bug</h1>
...
</body>
</html>

The obvious way to make this happen would have been this template:

<html>
<head><title>Bug System - {% block title %}{% endblock %}</title></
head>
<body>
<h1>{% block title %}{% endblock %}</h1>
{% block body %}{% endblock %}
</body>
</html>

but it doesn't work, because a block with the same name can't be
defined twice in the same block.

I asked in IRC what should I do, and got two possibilities:
1. Pass the title as an argument to the template.
2. Write the title twice in the template.

The problem with method 1 is that the title doesn't belong to the code
- it belongs to the template.
The problem with method 2 is that you have to write the title twice
(and I saw the DRY principle mentioned in a few places in the docs...)

After thinking about it, I've found another solution. Write this
template, and call it "base_helper.html":

<html>
<head><title>Bug System - {% block title %}{% endblock %}</title></
head>
<body>
<h1>{% block silly %}{% endblock %}</h1>
{% block body %}{% endblock %}
</body>
</html>

Also write this template, and call it "base.html":

{% extends "base_helper.html" %}
{% block silly %}{% block title %}{% endblock %}{% endblock %}

Now, if you render a template like this:

{% extends "base.html" %}
{% block title %}Page Title{% endblock %}
{% block body %}Page Body{% endblock %}

You'll get the desired result:

<html>
<head><title>Bug System - Page Title</title></head>
<body>
<h1>Page Title</h1>
Page Body
</body>
</html>

The obvious problem with this solution is that most people won't think
about it. And most people finding this code will have a hard time
understanding how it works.

(how it works: the second {% block title %} is enclosed by another
block, defined in another template, so you don't have two {% block
title %}s in the same file and everything is ok.)

Let me explain how I understand the "block" algorithm, which will help
me explain why currently multiple blocks with the same name in the
same template aren't allowed and how they can be made allowed.

The block algorithm goes like this. You are given an ordered list of
templates, starting from the most specific one and ending with the
least specific one. You go over them one by one. You also hold a
mapping from a block name to a string.
For each template, you go over it and render it. When encountering a
block, you check if it appears in the mapping. If it doesn't you
render the block, add the result to the rendered page, and also save
the result in your mapping. If it does appear in the mapping, it means
that you already rendered that block, and you ignore the contents of
the block in the template you are handling and replace it with the
saved result.
The result is the rendered last template, with all blocks handled as
described.

Now, why multiple blocks with the same name aren't allowed in the same
template? Because you won't know which one to render and store in the
mapping, and which one to ignore. If two blocks with the same name
appear in two different files, you have no problem - the block in the
more specific template will take precedence.

However, my description of the algorithm suggests how multiple blocks
with the same name in the same file can be handled: just go over them
one by one. The first block may be rendered, if no block with the same
name is defined in a more specific template, and the rest of the
blocks will never be rendered and will always be replaced.

This solution has a problem, though: Who said that the first block in
a template should be considered the meaningful one, and not the last
one, for example? Or, as the zen of python says: In the face of
ambiguity, refuse the temptation to guess.

For this I want to suggest a solution: When multiple blocks are
defined in one template, all the blocks which are not the first block
should be either:
* the same as the first block, or:
* empty.

This means that I would be allowed to write:

<html>
<head><title>Bug System - {% block title %}Page Title{% endblock %}</
title></head>
<body>
<h1>{% block title %}Page Title{% endblock %}</h1>
{% block body %}{% endblock %}
</body>
</html>

or:

<html>
<head><title>Bug System - {% block title %}Page Title{% endblock %}</
title></head>
<body>
<h1>{% block title %}{% endblock %}</h1>
{% block body %}{% endblock %}
</body>
</html>

but not:

<html>
<head><title>Bug System - {% block title %}Page Title 1{% endblock %}</
title></head>
<body>
<h1>{% block title %}Page Title 2{% endblock %}</h1>
{% block body %}{% endblock %}
</body>
</html>

(Of course, I could leave both blocks empty.)

What do you think about this idea?

Noam

P.S. I may be able to implement it by myself, but I wanted to get an
approval (or a disapproval, which I hope not) before.

SmileyChris

unread,
Jun 7, 2007, 4:17:49 PM6/7/07
to Django developers
Another solution is that multiple blocks with the same name inside a
template are allowed as long as the template doesn't extend that block
name (raise an error in that case).

This way, it doesn't matter about the "meaningful" block, because if
it's just the parent template which has two blocks, you only want to
replace all blocks of that name with the one in your child template
doing the extension so there's no worry about ambiguity.

Marty Alchin

unread,
Jun 7, 2007, 4:25:23 PM6/7/07
to django-d...@googlegroups.com

I'm +1 on this approach. That's how I would expect it to be most
commonly used (it's how I was hoping it would work), and it would
avoid template designers having to worry as much about how the innards
work.

-Gul

Ilya Semenov

unread,
Jun 7, 2007, 4:39:35 PM6/7/07
to Django developers
+1 on that. Have been in the same situtation and came up with the
exactly same approach on my mind.
Perhaps http://code.djangoproject.com/ticket/1513 should be reopened?

James Bennett

unread,
Jun 7, 2007, 5:02:58 PM6/7/07
to django-d...@googlegroups.com
On 6/7/07, Noam <noam...@gmail.com> wrote:
> I want every page in my site to have a title. I want the title to
> appear both in the browser title and in the page itself. An example of
> the HTML I want is this:
>
> <html>
> <head><title>Bug System - Report a New Bug</title></head>
> <body>
> <h1>Report a New Bug</h1>

This seems like an unusual case, though. Consider what another
template, say, 'bug_detail', would look like:

<html>
<head>
<title>Bug System - Bug #43 - Using blocks as variables doesn't work</title>
</head>
<body>
<h1>Bug #43 - Using blocks as variables doesn't work</title>

Now, in this case the title is obviously going to be pulled from
fields on a "bug" object pulled from the database and, more
importantly, the two "blocks" aren't going to match up (it's common to
include a site name or section name in the 'title' element, but far
less common to include it in a a header).

In the uncommon case of exactly-repeated hard-coded text in the
template, the net effect of this would be to change blocks from part
of the inheritance mechanism into another way to do variables in
templates (in this case, assigned by the template author within the
template).

I realize that's not really what's being asked for here, but I have a
hard time believing it wouldn't be used for that -- rather than
organize data in the view, people would just start defining lots of
blocks up-front and reusing them, variable-fashion, throughout the
template, and we'd be one step closer to having a programming language
instead of a templating language.

Additionally, since I'm pretty sure this is the uncommon case rather
than the common case, I'm not sure it's worth further complicating
template parsing and rendering by allowing blocks to be re-used
arbitrary numbers of times.

Combining these two objections, I'd give it a strong -1.


--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."

Noam

unread,
Jun 7, 2007, 6:33:55 PM6/7/07
to Django developers

I think that in practice it doesn't matter a lot whether your method
is chosen or mine, since I think that the use case is pretty much what
I described. However, I like my method better since (I think) it keeps
the block algorithm simpler to understand, and "Simple is better than
complex" - it keeps the current algorithm, and clarifies what should
be done if multiple blocks with the same name are encountered in the
same template. My method keeps the fact that in the resulting page,
every block with the same name is replaced with the same content, and
it doesn't add a new restriction about other related templates.

Sorry about my long sentences. I just gave this a bit of thought, and
I think that my method is nicer, and Ilya thinks the same, and both
methods solve the use case just as well, so...

Noam

unread,
Jun 7, 2007, 6:49:33 PM6/7/07
to Django developers
On Jun 8, 12:02 am, "James Bennett" <ubernost...@gmail.com> wrote:

> On 6/7/07, Noam <noamr...@gmail.com> wrote:
>
> > I want every page in my site to have a title. I want the title to
> > appear both in the browser title and in the page itself. An example of
> > the HTML I want is this:
>
> > <html>
> > <head><title>Bug System - Report a New Bug</title></head>
> > <body>
> > <h1>Report a New Bug</h1>
>
> This seems like an unusual case, though. Consider what another
> template, say, 'bug_detail', would look like:
>
> <html>
> <head>
> <title>Bug System - Bug #43 - Using blocks as variables doesn't work</title>
> </head>
> <body>
> <h1>Bug #43 - Using blocks as variables doesn't work</title>
>
> Now, in this case the title is obviously going to be pulled from
> fields on a "bug" object pulled from the database and, more
> importantly, the two "blocks" aren't going to match up (it's common to
> include a site name or section name in the 'title' element, but far
> less common to include it in a a header).
>
I don't think it's uncommon. I wrote a perfectly simple site and
writing the same title at the top of the window and in the page was
the right thing to do. It doesn't have to be the case for all sites,
but it doesn't make it uncommon - the fact is that at least
SmileyChris, Marty, Ilya and I had the same need.

> In the uncommon case of exactly-repeated hard-coded text in the
> template, the net effect of this would be to change blocks from part
> of the inheritance mechanism into another way to do variables in
> templates (in this case, assigned by the template author within the
> template).
>

I don't see how you will be able to use blocks as variables. The only
thing you can do with a block is to display it in the rendered page -
you can't use it in any other way. And if you want to write the same
thing a few times in your page, what's wrong with it?

Also, everything that you would be able to do if my suggestion is
accepted you can do right now, using the trick I described. It's just
pretty ugly.

> I realize that's not really what's being asked for here, but I have a
> hard time believing it wouldn't be used for that -- rather than
> organize data in the view, people would just start defining lots of
> blocks up-front and reusing them, variable-fashion, throughout the
> template, and we'd be one step closer to having a programming language
> instead of a templating language.

This may be a reason to force writing the same content in all blocks
of the same name in a template. However, I don't really understand the
usage you describe - can you give an example?


>
> Additionally, since I'm pretty sure this is the uncommon case rather
> than the common case, I'm not sure it's worth further complicating
> template parsing and rendering by allowing blocks to be re-used
> arbitrary numbers of times.

Just another comment - I'm not sure it will complicate template
parsing a lot. As I said, the same thing can be done in a more ugly
way. It's basically just lifting an unneeded requirement. But this can
be judged by seeing a working implementation.

Noam

Marty Alchin

unread,
Jun 7, 2007, 7:52:50 PM6/7/07
to django-d...@googlegroups.com
I should note that I withdraw my +1. Not only does James bring up some
good points, I just realized that Noam's example can be done without
the whole {%block silly %} thing.

Just to test all this out, I just defined {% block title %} in two
different inherited templates and filled it in in the third template,
and it worked just fine.

structure.html:
<html>
<head>
<title>My Site: {% block title %}{% endblock %}</title>
</head>
<body>{% body theme %}{% endblock %}</body>
</html>

body.html:
{% extends 'structure.html' %}
{% block theme %}


<h1>{% block title %}{% endblock %}</h1>

{% endblock %}

<individual page template>.html
{% extends 'body.html' %}


{% block title %}Page Title{% endblock %}

Obviously there'd be more going on in those, but that demonstrates the
point. The page title gets a prefix, while the content title doesn't,
but both receive the same text, as written in the page template. I've
tested this in both 0.95 and in SVN.

I'd say I'm -0 on this now.

-Gul

SmileyChris

unread,
Jun 7, 2007, 7:59:08 PM6/7/07
to Django developers

On Jun 8, 10:33 am, Noam <noamr...@gmail.com> wrote:
> ... However, I like my method better since (I think) it keeps

> the block algorithm simpler to understand, and "Simple is better than
> complex" - it keeps the current algorithm, and clarifies what should
> be done if multiple blocks with the same name are encountered in the
> same template.
Each to their own. I just provided a suggestion since your way just
seemed confusing (perhaps introducing the need for long sentences?).
Especially with the introduction of a strange "all the blocks which
are not the first block should be either the same as the first block,
or empty." rule.

> My method keeps the fact that in the resulting page,
> every block with the same name is replaced with the same content, and
> it doesn't add a new restriction about other related templates.

This isn't really introducing a new restriction, just relaxing a
current one.

> I think that my method is nicer, and Ilya thinks the same, and both
> methods solve the use case just as well, so...

>From the thread, it isn't clear exactly which method Ilya preferred.
You also assume in your following message that I had a "need" for this
- I was merely presenting a more simplistic solution.
Call me +0 on my suggestion, -0 on the overall proposal ;)

James Bennett

unread,
Jun 7, 2007, 8:06:12 PM6/7/07
to django-d...@googlegroups.com
On 6/7/07, Noam <noam...@gmail.com> wrote:
> I don't see how you will be able to use blocks as variables. The only
> thing you can do with a block is to display it in the rendered page -
> you can't use it in any other way. And if you want to write the same
> thing a few times in your page, what's wrong with it?

{% block site_name %}Zombo.com{% endblock %}
{% block welcome_message %}Welcome! {% endblock %}
{% today_date %}{% now "%m %d, %Y" %}{% endblock %}
<html>
<head>
<title>{% block site_name %}{% endblock %} - {% block welcome_message
%}{% endblock %} -- {% block today_date %}{% endblock %}</title>
<meta http-equiv="Last-Modified" content="{% block today_date %}{% endblock %}">
</head>
<body>
<h1>{% block site_name %}{% endblock %} - {% block welcome_message
%}{% endblock %} -- {% block today_date %}{% endblock %}</h1>

<p>{% block welcome_message %}{% endblock %} You can do anything at {%
block site_name %}{% endblock %}!</p>

etc., etc.

> Just another comment - I'm not sure it will complicate template
> parsing a lot. As I said, the same thing can be done in a more ugly
> way. It's basically just lifting an unneeded requirement. But this can
> be judged by seeing a working implementation.

The complication will be in rendering of blocks. As it stands,
rendering a block is a (somewhat) simple process because of the "each
block is used once" requirement; there's a fairly limited number of
places you have to look to determine whether the current template is
overriding the block or should pick up content from a parent (and if
so, which parent). Allowing blocks to be reused multiple times could
end up requiring the template system to search a lot more places
before it can reliably make that decision, and that would complicate
rendering and probably make things run more slowly.

Tai Lee

unread,
Jun 8, 2007, 6:36:21 AM6/8/07
to Django developers
I'm -0 on this too, even though I have run into a situation where I
wanted a block to appear twice in a base template, and the content of
the block was defined in the view template (can't remember the
details). The additional complication and strange rules are not worth
the benefit (and I'm not even sure it is a benefit).

Noam

unread,
Jun 8, 2007, 9:08:34 AM6/8/07
to Django developers
On Jun 8, 2:52 am, "Marty Alchin" <gulop...@gamemusic.org> wrote:
> I should note that I withdraw my +1. Not only does James bring up some
> good points, I just realized that Noam's example can be done without
> the whole {%block silly %} thing.
>
I admit that it looks better, because you gave meaning to the blocks,
but you still have to use two files when one would have sufficed and
would have stated clearly what you want. You can also say that
although it looks better, most people won't think of this solution by
themselves.

Noam

Marty Alchin

unread,
Jun 8, 2007, 9:14:57 AM6/8/07
to django-d...@googlegroups.com
On 6/8/07, Noam <noam...@gmail.com> wrote:
> I admit that it looks better, because you gave meaning to the blocks,
> but you still have to use two files when one would have sufficed and
> would have stated clearly what you want.

Well, one might suffice for some, but I have a 4-layer inheritance
scheme already (long story), which worked out quite naturally to use
the method I described.

As for the notion of people not thinking of this themselves, why not
write up a Wiki article about it? It really seems to be more of an
education issue now, rather than a code issue.

-Gul

Noam

unread,
Jun 8, 2007, 9:25:26 AM6/8/07
to Django developers
Let me improve my suggestion, so that it mostly solves James' concern
and can be explained in one sentence:

---------
Multiple blocks with the same name would be allowed, as long as all of
them have the same content.
---------

This would solve my (and others, not including SmileyChris, sorry!)
problem neatly - the template would be:

<html>
<head>
<title>Bug System - {% block title %}Page Title{% endblock %}</title>
</head>
<body>

<h1>{% block title %}Page Title{% block title %}</h1>
{% block body %}
</body>
</html>

It would mostly solve James' concern because his example won't work -
You can't define a block at the beginning of the file and then use it
a few times. It's true that you can define it in a more specific
template, but I believe that most people simply won't think of that.

And this improved suggestion has no complicated rules, and causes no
ambiguities.

Well, what do you think?

Noam

Marty Alchin

unread,
Jun 8, 2007, 9:35:37 AM6/8/07
to django-d...@googlegroups.com
On 6/8/07, Noam <noam...@gmail.com> wrote:
> Let me improve my suggestion, so that it mostly solves James' concern
> and can be explained in one sentence:
>
> ---------
> Multiple blocks with the same name would be allowed, as long as all of
> them have the same content.
> ---------

I'm not sure I like that as it stands. In your example, you provide
content for both of the blocks, which clearly violates DRY, since (by
virtue of your new rule) they're always going to be identical. If a
template designer ever has to update one, they have to update both.

I'm still -0 on this, but I might be +0 (yeah, big change) if the rule
stated that in order to have multiple blocks with the same name, all
must be EMPTY. This would allow a child template to fill in multiple
blocks, while not giving template designers a reason to get confused
by duplicate content.

I'm still not sold on the idea as a whole though, it just seems like
any support for it would be quite a mess, whether for the
implementation or the users.

-Gul

Malcolm Tredinnick

unread,
Jun 8, 2007, 9:47:56 AM6/8/07
to django-d...@googlegroups.com
On Fri, 2007-06-08 at 13:25 +0000, Noam wrote:
> Let me improve my suggestion, so that it mostly solves James' concern
> and can be explained in one sentence:
>
> ---------
> Multiple blocks with the same name would be allowed, as long as all of
> them have the same content.
> ---------
>
> This would solve my (and others, not including SmileyChris, sorry!)
> problem neatly - the template would be:
>
> <html>
> <head>
> <title>Bug System - {% block title %}Page Title{% endblock %}</title>
> </head>
> <body>
> <h1>{% block title %}Page Title{% block title %}</h1>
> {% block body %}
> </body>
> </html>

Aside from the "urgh!" factor from writing the content in multiple
times, if you are going to do this, why not just create a "reuse-block"
tag that re-inserts the block value the template parser has already
worked out previously? Doesn't need any change to the behaviour of
"block" then.

Regards,
Malcolm


Noam Raphael

unread,
Jun 8, 2007, 9:54:23 AM6/8/07
to django-d...@googlegroups.com
On 08/06/07, Marty Alchin <gulo...@gamemusic.org> wrote:
>
> On 6/8/07, Noam <noam...@gmail.com> wrote:
> > Let me improve my suggestion, so that it mostly solves James' concern
> > and can be explained in one sentence:
> >
> > ---------
> > Multiple blocks with the same name would be allowed, as long as all of
> > them have the same content.
> > ---------
>
> I'm not sure I like that as it stands. In your example, you provide
> content for both of the blocks, which clearly violates DRY, since (by
> virtue of your new rule) they're always going to be identical. If a
> template designer ever has to update one, they have to update both.
>
If the time comes when you need a page with a different title in the
window and in the heading, you can always extend your base template
like this:

<html>
<head>
<title>{% block windowtitle %}Bug System - {% block title %}Page
Title{% endblock %}{% endblock %}</title>
</head>
</body>
<h1>{% block headingtitle %}{% block title %}Page Title{% endblock
%}{% endblock %}</h1>


{% block body %}Page Body{% endblock %}

</body>
</html>

With that template, the original specific template would continue to work:

{% extends "base.html" %}
{% block title %}Post a New Bug{% endblock %}
{% block body %}...{% endblock %}

But you will also be able to write a template like this:

{% extends "base.html" %}
{% block windowtitle %}Bug 12345{% endblock %}
{% block headingtitle %}Bug 12345 - Allow multiple blocks with the
same name{% endblock %}
{% block body %}...{% endblock %}

Does it help?

> I'm still -0 on this, but I might be +0 (yeah, big change) if the rule
> stated that in order to have multiple blocks with the same name, all
> must be EMPTY. This would allow a child template to fill in multiple
> blocks, while not giving template designers a reason to get confused
> by duplicate content.
>

I don't think it's confusing that both {% block title %} have the same
content - it just shows that they will get the same contents in the
rendered page.

> I'm still not sold on the idea as a whole though, it just seems like
> any support for it would be quite a mess, whether for the
> implementation or the users.

About the implementation - I think that it is best to try to implement
and see how complicated is it. About the users - I don't think it will
be a mess. People with a need like mine will just write two empty
blocks and everything will work as they expected, or will write one
empty block and one full block, will get an error stating that
multiple blocks with the same name in the same template must have the
same content, and fix it. I don't see what further complications
should arise.
>

Noam Raphael

unread,
Jun 8, 2007, 9:59:44 AM6/8/07
to django-d...@googlegroups.com
> Aside from the "urgh!" factor from writing the content in multiple
> times, if you are going to do this, why not just create a "reuse-block"
> tag that re-inserts the block value the template parser has already
> worked out previously? Doesn't need any change to the behaviour of
> "block" then.
>
As I see it, because you:
1. Add another tag that users should be aware of.
2. Encourage users to do what James was afraid that they will do.

I don't see this as "changing the behavior of blocks". I think my
suggestion is merely to relax the restriction - multiple blocks with
the same name are not disallowed altogether - they are allowed, as
long as they all have the same content.

Noam

Collin Grady

unread,
Jun 8, 2007, 5:26:57 PM6/8/07
to Django developers
This came up on IRC the other day and I had an idea on the subject -
I'm not sure if this would actually work well or not, but it can't
hurt to toss it out there :)

I was thinking of some format like so:

{% block foo,bar %}New content{% endblock %}

And having that now override both foo and bar. As for the handling of
block.super, I was thinking that {{ block.super }} would use the
proper parent content for the block it's replacing, so for instance
doing this:

{% block foo,bar %}{{ block.super }} - Some Site{% endblock %}

Would use foo's content when replacing foo, and bar's content when
replacing bar. In addition, if it's at all possible, I was thinking
something along the lines of {{ block.foo.super }} or
{{ block.super.foo }} could be used to grab one specific block's
content (less useful IMO, but I dunno)

Using this idea, the bug tracker title example would look pretty
straightforward:

# parent
<html>
<head>
<title>{% block title %}Bug System - {% endblock %}</title>
</head>
<body>
<h1>{% block header %}{% endblock %}</h1>

# child
{% block title,header %}{{ block.super }}{{ object.title }}{% endblock
%}

Which would then render as expected - title would have "Bug System - "
placed in front of the object's title, while header would not.

Ok, I think that about covers my idea, but I'm not really attached to
it if there are problems I'm not noticing :)

Max Battcher

unread,
Jun 8, 2007, 8:54:16 PM6/8/07
to django-d...@googlegroups.com
I had yet another suggestion: use template vars for block repetitions, such as:

<html>
<head>
<title>{% block title %}Page Title{% endblock %} | Some Site</title>
</head>
<body>
<h1>{{ block.title }}</h1>
</body>
</html>

Make the "block object" suitably lazy and in most cases I would think
it "should just work"... (I used {{ block.title }} rather than {{
blocks.title }} to mirror the existing {{ block.super }} var...)
Assuming the order of template rendering is what I remember thinking
it was...

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

Noam Raphael

unread,
Jun 9, 2007, 7:47:56 PM6/9/07
to Django developers
Ok, I've implemented my suggestion.

For those concerned about the complexity of implementation, it turns
out that all that's needed is a simple change in the block parser, to
make it return the same object for all blocks with the same name in a
template. The rendering code wasn't touched at all.

(In order to make sure that all blocks of the same name really had the
same content, I added an optional argument to the parse() method which
allows it to return the list of tokens from which a block was made.)

Where should I post the diff?

Noam

(By the way, the current SVN doesn't load the loader_tags module, at
least for me. I fixed it (or so it seems) by moving the line
"add_to_builtins('django.template.loader_tags')" from
template/loaders.py to template/__init__.py. Did I do something wrong
or is it a bug?)

Malcolm Tredinnick

unread,
Jun 9, 2007, 8:39:48 PM6/9/07
to django-d...@googlegroups.com
On Sun, 2007-06-10 at 02:47 +0300, Noam Raphael wrote:
> Ok, I've implemented my suggestion.
>
> For those concerned about the complexity of implementation, it turns
> out that all that's needed is a simple change in the block parser, to
> make it return the same object for all blocks with the same name in a
> template. The rendering code wasn't touched at all.
>
> (In order to make sure that all blocks of the same name really had the
> same content, I added an optional argument to the parse() method which
> allows it to return the list of tokens from which a block was made.)
>
> Where should I post the diff?

The traditional place would be to open a ticket in Trac.

Have realistic expectations, though. This feature hasn't won a lot of
support in this thread and there have been some reasonable arguments
made against it on design philosophy grounds. The only core developer to
comment on it so far (me) has been against the idea of extending block
tag behaviour like this. So the ticket will fairly rapidly move to
"design decision needed" whilst we think about it a bit (I personally
don't resolve as "wontfix" tickets like that immediately, since it's
worthwhile to think about it for a few days or weeks). It may well be
closed on account of not being an enhancement we want to make. I'm not
saying the decision is already made; just engaging in a bit of crystal
ball gazing and predicting a possible future.

By the way, one advantage of writing the functionality you want as an
extra tag (something not called "block") is that you (or anybody else
who wants to work this way) can easily use it as a third-party tag, so
it doesn't need to be part of core.

Whilst I completely appreciate you are trying to help everybody here, we
cannot possibly include every feature that everybody wants (or even that
every group of two dozen people want) because then Django would contain
a million features and about as many bugs. A lot of enhancement requests
are turned down for this reason and it's one reason that extending the
template tag and filter system by third-party developers has been made
so straightforward.

All that being said, open a ticket and attach the patch. It won't hurt
to give it a read. Or make it a third-party tag and post it to Django
snippets.

> (By the way, the current SVN doesn't load the loader_tags module, at
> least for me. I fixed it (or so it seems) by moving the line
> "add_to_builtins('django.template.loader_tags')" from
> template/loaders.py to template/__init__.py. Did I do something wrong
> or is it a bug?)

The {% block %} tag seems to work currently (it's tested as part of the
test suite), so that would seem to suggested loader_tags is being
imported correctly. Note that the import of that file happens as part of
template.get_library(), which is called by add_to_builtins(). So the
loader_tags file is imported, just not explicitly. No changes seem to be
needed there, unless I'm misunderstanding what you are saying.

Regards,
Malcolm

Noam Raphael

unread,
Jun 11, 2007, 6:01:47 AM6/11/07
to django-d...@googlegroups.com
Ok, I posted my patch at http://code.djangoproject.com/ticket/4529

On 10/06/07, Malcolm Tredinnick <mal...@pointy-stick.com> wrote:
> By the way, one advantage of writing the functionality you want as an
> extra tag (something not called "block") is that you (or anybody else
> who wants to work this way) can easily use it as a third-party tag, so
> it doesn't need to be part of core.

I think that if it's not accepted, the easiest way to accomplish what
I want would be my hack. This way I won't have to use a different name
for blocks, and I won't have to maintain an external tag system. It's
still a hack, though.


>
> > (By the way, the current SVN doesn't load the loader_tags module, at
> > least for me. I fixed it (or so it seems) by moving the line
> > "add_to_builtins('django.template.loader_tags')" from
> > template/loaders.py to template/__init__.py. Did I do something wrong
> > or is it a bug?)
>
> The {% block %} tag seems to work currently (it's tested as part of the
> test suite), so that would seem to suggested loader_tags is being
> imported correctly. Note that the import of that file happens as part of
> template.get_library(), which is called by add_to_builtins(). So the
> loader_tags file is imported, just not explicitly. No changes seem to be
> needed there, unless I'm misunderstanding what you are saying.
>

I did a fresh SVN checkout, and made a new project, and run
./manage.py shell, and got:

noam@baruch:/tmp/mysite$ ./manage.py shell
Python 2.5.1 (r251:54863, May 2 2007, 16:56:35)
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template, Context
>>> t = Template('''{% block title %}Hello{% end block %}''')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/noam/lib/python/django/template/__init__.py", line 162,
in __init__
self.nodelist = compile_string(template_string, origin)
File "/home/noam/lib/python/django/template/__init__.py", line 178,
in compile_string
return parser.parse()
File "/home/noam/lib/python/django/template/__init__.py", line 284, in parse
self.invalid_block_tag(token, command)
File "/home/noam/lib/python/django/template/__init__.py", line 328,
in invalid_block_tag
raise self.error( token, "Invalid block tag: '%s'" % command)
TemplateSyntaxError: Invalid block tag: 'block'

Thanks,
Noam

Malcolm Tredinnick

unread,
Jun 11, 2007, 6:07:27 AM6/11/07
to django-d...@googlegroups.com
On Mon, 2007-06-11 at 13:01 +0300, Noam Raphael wrote:
[...]

> I did a fresh SVN checkout, and made a new project, and run
> ./manage.py shell, and got:
>
> noam@baruch:/tmp/mysite$ ./manage.py shell
> Python 2.5.1 (r251:54863, May 2 2007, 16:56:35)
> [GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
> (InteractiveConsole)
> >>> from django.template import Template, Context
> >>> t = Template('''{% block title %}Hello{% end block %}''')
> Traceback (most recent call last):
> File "<console>", line 1, in <module>
> File "/home/noam/lib/python/django/template/__init__.py", line 162,
> in __init__
> self.nodelist = compile_string(template_string, origin)
> File "/home/noam/lib/python/django/template/__init__.py", line 178,
> in compile_string
> return parser.parse()
> File "/home/noam/lib/python/django/template/__init__.py", line 284, in parse
> self.invalid_block_tag(token, command)
> File "/home/noam/lib/python/django/template/__init__.py", line 328,
> in invalid_block_tag
> raise self.error( token, "Invalid block tag: '%s'" % command)
> TemplateSyntaxError: Invalid block tag: 'block'

Bizarre, but true. I guess it's because we're always importing template
loaders or something in real-world cases. *shrug*.

This bit's worth fixing, in any case. Good catch.

Regards,
Malcolm

Reply all
Reply to author
Forward
0 new messages