Improvement suggestion for {% url %}

2 views
Skip to first unread message

!张沈鹏(电子科大 08年毕业)

unread,
Aug 7, 2007, 5:10:31 AM8/7/07
to django-d...@googlegroups.com
I like if tag url can use like this maybe more useful .
{% url music "rock","112" as music_url %}

for example , I write some thing can count the access of pages by url.
The counter is generic , it's only save the url .
then I can write

{% url music "rock",112 as music_url %}
{% access_count music_url %}

And use with forloop I can show a list of music and the access number.

--
欢迎访问我的博客:
http://zsp.javaeye.com/

--张沈鹏

张沈鹏

unread,
Aug 7, 2007, 5:16:45 AM8/7/07
to Django developers
sorry , spell error .
I like if tag url -> I think if tag url

Collin Grady

unread,
Aug 8, 2007, 3:31:00 AM8/8/07
to Django developers
Couldn't you just use reverse() in your custom tag?

!张沈鹏(电子科大 08年毕业)

unread,
Aug 8, 2007, 3:46:53 AM8/8/07
to django-d...@googlegroups.com
because if I want to get the link first , then get the count number .
if I just use reverse() in my custom tag, I have to write like below

<a href="{% url music "rock",112 %}">xxx</a>
Digg:{% access_count_url music "rock",112 %}

I write the same things twice , and if I want write a link such as
"add to shopping list" I have to write the same thing
<a onclick="add({% url music "rock",112 %})" >Add to shopping list</a>

I find the url always use more than once , so I suggest if can use like this


{% url music "rock","112" as music_url %}

maybe more convenience

2007/8/8, Collin Grady <cgr...@gmail.com>:


>
> Couldn't you just use reverse() in your custom tag?
>
>
> >
>

!张沈鹏(电子科大 08年毕业)

unread,
Aug 8, 2007, 6:11:25 AM8/8/07
to django-d...@googlegroups.com
sorry , fix some error

from django.conf import settings
from django.template import Node

class URLNode(Node):
def __init__(self, view_name, args,kwargs,as_name):
self.view_name = view_name
self.args = args
self.kwargs = kwargs
self.as_name = as_name

def render(self, context):
from django.core.urlresolvers import reverse, NoReverseMatch
args = [arg.resolve(context) for arg in self.args]
kwargs = dict([(smart_str(k,'ascii'), v.resolve(context)) for
k, v in self.kwargs.items()])
try:
url=reverse(self.view_name, args=args, kwargs=kwargs)
except NoReverseMatch:
try:
project_name = settings.SETTINGS_MODULE.split('.')[0]
url=reverse(project_name + '.' + self.view_name,
args=args, kwargs=kwargs)
except NoReverseMatch:
url=''
if self.as_name:
context[self.as_name]=url
return url

def url(parser, token):
bits = token.split_contents()
bit_len=len(bits)
if bit_len < 2:
raise TemplateSyntaxError, "'%s' takes at least one argument
(path to a view)" % bits[0]
args = []
kwargs = {}
as_name=None
if bit_len>3:
as_name=bits[-1]
if bit_len==3 or bit_len>4:
for arg in bits[2].split(','):
if '=' in arg:
k, v = arg.split('=', 1)
k = k.strip()
kwargs[k] = parser.compile_filter(v)
else:
args.append(parser.compile_filter(arg))

return URLNode(bits[1], args, kwargs,as_name)
url = register.tag(url)

2007/8/8, !张沈鹏(电子科大 08年毕业) <zsp...@gmail.com>:
> This code is what I said
>
> from django.conf import settings
>
> class URLNode(Node):
> def __init__(self, view_name, args,kwargs,as_name):
> self.view_name = view_name
> self.args = args
> self.kwargs = kwargs
> self.as_name = as_name
>
> def render(self, context):
> from django.core.urlresolvers import reverse, NoReverseMatch
> args = [arg.resolve(context) for arg in self.args]
> kwargs = dict([(smart_str(k,'ascii'), v.resolve(context)) for
> k, v in self.kwargs.items()])
> try:
> url=reverse(self.view_name, args=args, kwargs=kwargs)
> except NoReverseMatch:
> try:
> project_name = settings.SETTINGS_MODULE.split('.')[0]
> url=reverse(project_name + '.' + self.view_name,
> args=args, kwargs=kwargs)
> except NoReverseMatch:
> url=''
> if self.as_name:
> context[self.as_name]=url
> return url
>
> def url(parser, token):
> bits = token.split_contents()
> if len(bits) < 2:
> raise TemplateSyntaxError, "'%s' takes at least one argument
> (path to a view)" % bits[0]
> args = []
> kwargs = {}
> as_name=None
> if len(bits) > 2:
> for arg in bits[2].split(','):
> if '=' in arg:
> k, v = arg.split('=', 1)
> k = k.strip()
> kwargs[k] = parser.compile_filter(v)
> else:
> args.append(parser.compile_filter(arg))
> if len(bits)>3:
> as_name=bits[3]
> return URLNode(bits[1], args, kwargs,as_name)
> url = register.tag(url)
>
> 2007/8/8, !张沈鹏(电子科大 08年毕业) <zsp...@gmail.com>:

!张沈鹏(电子科大 08年毕业)

unread,
Aug 8, 2007, 5:56:25 AM8/8/07
to django-d...@googlegroups.com

from django.conf import settings

2007/8/8, !张沈鹏(电子科大 08年毕业) <zsp...@gmail.com>:

Malcolm Tredinnick

unread,
Aug 9, 2007, 8:16:13 AM8/9/07
to django-d...@googlegroups.com
On Wed, 2007-08-08 at 15:46 +0800, !张沈鹏(电子科大 08年毕业) wrote:
> because if I want to get the link first , then get the count number .
> if I just use reverse() in my custom tag, I have to write like below
>
> <a href="{% url music "rock",112 %}">xxx</a>
> Digg:{% access_count_url music "rock",112 %}
>
> I write the same things twice , and if I want write a link such as
> "add to shopping list" I have to write the same thing
> <a onclick="add({% url music "rock",112 %})" >Add to shopping list</a>
>
> I find the url always use more than once , so I suggest if can use like this
> {% url music "rock","112" as music_url %}
> maybe more convenience

A general design observation, rather than making a specialised
modification to just one tag like this -- which leads to requests to
modify other tags similarly and it never ends -- it's probably better to
try to work out a general extension to the "with" tag for aliases like
this. Recall that the "with" tag is designed to cache variable lookups
at the moment. Caching template tag results might not be a terrible
extension.

I'm not sure what the syntax would look like at the moment, but it's
something I need to think about: it would help solve one or two i18n
rough spots, too. This is teetering on the edge of "variables in
templates", but aliasing is pretty common even in functional languages
as a typing saver type of sugar.

I'm not sure if there's a hidden gotcha here, but I would rather
investigate in that direction than adding aliasing hooks to tags as
people decide they might want them.

Regards,
Malcolm

--
On the other hand, you have different fingers.
http://www.pointy-stick.com/blog/

SmileyChris

unread,
Aug 9, 2007, 5:37:05 PM8/9/07
to Django developers
On Aug 10, 12:16 am, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:

> I'm not sure what the syntax would look like at the moment, but it's
> something I need to think about: it would help solve one or two i18n
> rough spots, too.

{% alias my_url %}{% url music "rock","112" %}{% endalias %}
{{ my_url }} {{ my_url }} {{ my_url }}

Seems simple enough.

!张沈鹏(电子科大 08年毕业)

unread,
Aug 9, 2007, 10:06:08 PM8/9/07
to django-d...@googlegroups.com
2007/8/10, SmileyChris <smile...@gmail.com>:

good idea , I has write code for this (in this email's attachment) .

I want to post to http://www.djangosnippets.org/snippets , but
something seems happened as below .
"""
Error

There's been an internal error on the server; it probably wasn't
anything you did, so don't worry too much about it. The site
administrators have been emailed with the details, and they'll
probably get it fixed real soon.
"""


> Seems simple enough.

zsp_tags.py

Malcolm Tredinnick

unread,
Aug 9, 2007, 10:16:41 PM8/9/07
to django-d...@googlegroups.com

Hmmm.. maybe, but..

One thing I like about the "with" tag is that it is scoped. Outside of
the tag block, the alias had no meaning, so their was no namespace
pollution. Your proposal puts the alias into the page's namespace for
all time (I guess it inherits through extended templates, too).

That's why I was having trouble coming up with something already: my
idea of perfect would be a tag has a way to specify both what it is
aliasing and what it's scope is. Without ugliness like {% with {% ... %}
as foo %}. Maybe a tag like "alias" should only live in its containing
"block" tag, if any.

It would also be nice if there was a way to unify variable lookup
aliasing and tag result aliasing, so that you don't have to think too
hard about which tag to use. Having both "with" and "alias" is not
ideal. It'll lead to lots of user blunders. Making something hard to use
incorrectly is a good goal to aim for.

This isn't something we have to solve overnight, so it's worth thinking
about a bit more, I feel. Those are the rough design ideas I've have
when mulling this over. Maybe I'm high, but probably not.

Regards,
Malcolm

--
No one is listening until you make a mistake.
http://www.pointy-stick.com/blog/

SmileyChris

unread,
Aug 10, 2007, 12:39:21 AM8/10/07
to Django developers

On Aug 10, 2:16 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:


> On Thu, 2007-08-09 at 21:37 +0000, SmileyChris wrote:
> > On Aug 10, 12:16 am, Malcolm Tredinnick <malc...@pointy-stick.com>
> > wrote:
> > > I'm not sure what the syntax would look like at the moment, but it's
> > > something I need to think about: it would help solve one or two i18n
> > > rough spots, too.
>
> > {% alias my_url %}{% url music "rock","112" %}{% endalias %}
> > {{ my_url }} {{ my_url }} {{ my_url }}
>
> > Seems simple enough.
>
> Hmmm.. maybe, but..
>
> One thing I like about the "with" tag is that it is scoped. Outside of
> the tag block, the alias had no meaning, so their was no namespace
> pollution. Your proposal puts the alias into the page's namespace for
> all time (I guess it inherits through extended templates, too).

{% alias my_url %}{% url music "rock","112" %}{% do %}
{{ my_url }} {{ my_url }} {{ my_url }}
{% endalias %}

You could potentially extend it like:
{% alias a %}A{% alias b %}B{% do %}
{{ a }} {{ b }} {{ a }}
{% endalias %}
But perhaps that gets confusing having one end and two opening tags...

The primary tag could alternately be called {% define %}

> It would also be nice if there was a way to unify variable lookup
> aliasing and tag result aliasing, so that you don't have to think too
> hard about which tag to use. Having both "with" and "alias" is not
> ideal. It'll lead to lots of user blunders. Making something hard to use
> incorrectly is a good goal to aim for.

Hrm... Both behaviours could be combined easy enough:

{% with myvar %}x{% do %}...{% endwith %}

{% with "x" as myvar %}{% do %}...{% endwith %}
or {% with "x" as myvar %}...{% endwith %} (keeping backwards
compatibility, but breaking the consistency of the new tag behaviour a
bit)

Reply all
Reply to author
Forward
0 new messages