Commit c068bc18 authored by Jacob Kaplan-Moss's avatar Jacob Kaplan-Moss
Browse files

Merge branch 'url-tag-asvar'

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8716 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 2ca8cf36
Loading
Loading
Loading
Loading
+39 −12
Original line number Diff line number Diff line
@@ -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):
@@ -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
+23 −0
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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'),