Loading django/template/defaulttags.py +39 −12 Original line number Diff line number Diff line Loading @@ -351,22 +351,40 @@ class TemplateTagNode(Node): return self.mapping.get(self.tagtype, '') class URLNode(Node): def __init__(self, view_name, args, kwargs): def __init__(self, view_name, args, kwargs, asvar): self.view_name = view_name self.args = args self.kwargs = kwargs self.asvar = asvar 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 to look up the URL twice: once given the view name, and again # relative to what we guess is the "main" app. If they both fail, # re-raise the NoReverseMatch unless we're using the # {% url ... as var %} construct in which cause return nothing. url = '' try: return reverse(self.view_name, args=args, kwargs=kwargs) url = reverse(self.view_name, args=args, kwargs=kwargs) except NoReverseMatch: project_name = settings.SETTINGS_MODULE.split('.')[0] return reverse(project_name + '.' + self.view_name, try: url = reverse(project_name + '.' + self.view_name, args=args, kwargs=kwargs) except NoReverseMatch: if self.asvar is None: raise if self.asvar: context[self.asvar] = url return '' else: return url class WidthRatioNode(Node): def __init__(self, val_expr, max_expr, max_width): Loading Loading @@ -1041,21 +1059,30 @@ def url(parser, token): The URL will look like ``/clients/client/123/``. """ bits = token.contents.split(' ', 2) bits = token.contents.split(' ') if len(bits) < 2: raise TemplateSyntaxError("'%s' takes at least one argument" " (path to a view)" % bits[0]) viewname = bits[1] args = [] kwargs = {} asvar = None if len(bits) > 2: for arg in bits[2].split(','): bits = iter(bits[2:]) for bit in bits: if bit == 'as': asvar = bits.next() break else: for arg in bit.split(","): if '=' in arg: k, v = arg.split('=', 1) k = k.strip() kwargs[k] = parser.compile_filter(v) else: elif arg: args.append(parser.compile_filter(arg)) return URLNode(bits[1], args, kwargs) return URLNode(viewname, args, kwargs, asvar) url = register.tag(url) #@register.tag Loading docs/ref/templates/builtins.txt +23 −0 Original line number Diff line number Diff line Loading @@ -675,6 +675,29 @@ The template tag will output the string ``/clients/client/123/``. <naming-url-patterns>`, you can refer to the name of the pattern in the ``url`` tag instead of using the path to the view. Note that if the URL you're reversing doesn't exist, you'll get an :exc:`NoReverseMatch` exception raised, which will cause your site to display an error page. **New in development verson:** If you'd like to retrieve a URL without displaying it, you can use a slightly different call: .. code-block:: html+django {% url path.to.view arg, arg2 as the_url %} <a href="{{ the_url }}">I'm linking to {{ the_url }}</a> This ``{% url ... as var %}`` syntax will *not* cause an error if the view is missing. In practice you'll use this to link to views that are optional: .. code-block:: html+django {% url path.to.view as the_url %} {% if the_url %} <a href="{{ the_url }}">Link to optional stuff</a> {% endif %} .. templatetag:: widthratio widthratio Loading tests/regressiontests/templates/tests.py +5 −0 Original line number Diff line number Diff line Loading @@ -896,6 +896,11 @@ class Templates(unittest.TestCase): 'url-fail02': ('{% url no_such_view %}', {}, urlresolvers.NoReverseMatch), 'url-fail03': ('{% url regressiontests.templates.views.client %}', {}, urlresolvers.NoReverseMatch), # {% url ... as var %} 'url-asvar01': ('{% url regressiontests.templates.views.index as url %}', {}, ''), 'url-asvar02': ('{% url regressiontests.templates.views.index as url %}{{ url }}', {}, '/url_tag/'), 'url-asvar03': ('{% url no_such_view as url %}{{ url }}', {}, ''), ### CACHE TAG ###################################################### 'cache01': ('{% load cache %}{% cache -1 test %}cache01{% endcache %}', {}, 'cache01'), 'cache02': ('{% load cache %}{% cache -1 test %}cache02{% endcache %}', {}, 'cache02'), Loading Loading
django/template/defaulttags.py +39 −12 Original line number Diff line number Diff line Loading @@ -351,22 +351,40 @@ class TemplateTagNode(Node): return self.mapping.get(self.tagtype, '') class URLNode(Node): def __init__(self, view_name, args, kwargs): def __init__(self, view_name, args, kwargs, asvar): self.view_name = view_name self.args = args self.kwargs = kwargs self.asvar = asvar 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 to look up the URL twice: once given the view name, and again # relative to what we guess is the "main" app. If they both fail, # re-raise the NoReverseMatch unless we're using the # {% url ... as var %} construct in which cause return nothing. url = '' try: return reverse(self.view_name, args=args, kwargs=kwargs) url = reverse(self.view_name, args=args, kwargs=kwargs) except NoReverseMatch: project_name = settings.SETTINGS_MODULE.split('.')[0] return reverse(project_name + '.' + self.view_name, try: url = reverse(project_name + '.' + self.view_name, args=args, kwargs=kwargs) except NoReverseMatch: if self.asvar is None: raise if self.asvar: context[self.asvar] = url return '' else: return url class WidthRatioNode(Node): def __init__(self, val_expr, max_expr, max_width): Loading Loading @@ -1041,21 +1059,30 @@ def url(parser, token): The URL will look like ``/clients/client/123/``. """ bits = token.contents.split(' ', 2) bits = token.contents.split(' ') if len(bits) < 2: raise TemplateSyntaxError("'%s' takes at least one argument" " (path to a view)" % bits[0]) viewname = bits[1] args = [] kwargs = {} asvar = None if len(bits) > 2: for arg in bits[2].split(','): bits = iter(bits[2:]) for bit in bits: if bit == 'as': asvar = bits.next() break else: for arg in bit.split(","): if '=' in arg: k, v = arg.split('=', 1) k = k.strip() kwargs[k] = parser.compile_filter(v) else: elif arg: args.append(parser.compile_filter(arg)) return URLNode(bits[1], args, kwargs) return URLNode(viewname, args, kwargs, asvar) url = register.tag(url) #@register.tag Loading
docs/ref/templates/builtins.txt +23 −0 Original line number Diff line number Diff line Loading @@ -675,6 +675,29 @@ The template tag will output the string ``/clients/client/123/``. <naming-url-patterns>`, you can refer to the name of the pattern in the ``url`` tag instead of using the path to the view. Note that if the URL you're reversing doesn't exist, you'll get an :exc:`NoReverseMatch` exception raised, which will cause your site to display an error page. **New in development verson:** If you'd like to retrieve a URL without displaying it, you can use a slightly different call: .. code-block:: html+django {% url path.to.view arg, arg2 as the_url %} <a href="{{ the_url }}">I'm linking to {{ the_url }}</a> This ``{% url ... as var %}`` syntax will *not* cause an error if the view is missing. In practice you'll use this to link to views that are optional: .. code-block:: html+django {% url path.to.view as the_url %} {% if the_url %} <a href="{{ the_url }}">Link to optional stuff</a> {% endif %} .. templatetag:: widthratio widthratio Loading
tests/regressiontests/templates/tests.py +5 −0 Original line number Diff line number Diff line Loading @@ -896,6 +896,11 @@ class Templates(unittest.TestCase): 'url-fail02': ('{% url no_such_view %}', {}, urlresolvers.NoReverseMatch), 'url-fail03': ('{% url regressiontests.templates.views.client %}', {}, urlresolvers.NoReverseMatch), # {% url ... as var %} 'url-asvar01': ('{% url regressiontests.templates.views.index as url %}', {}, ''), 'url-asvar02': ('{% url regressiontests.templates.views.index as url %}{{ url }}', {}, '/url_tag/'), 'url-asvar03': ('{% url no_such_view as url %}{{ url }}', {}, ''), ### CACHE TAG ###################################################### 'cache01': ('{% load cache %}{% cache -1 test %}cache01{% endcache %}', {}, 'cache01'), 'cache02': ('{% load cache %}{% cache -1 test %}cache02{% endcache %}', {}, 'cache02'), Loading