Ticket #2606: 2606.4.diff

File 2606.4.diff, 6.2 KB (added by Ivan Sagalaev <Maniac@…>, 8 years ago)

Patch + docs + tests

  • django/template/defaulttags.py

     
    315315    def render(self, context):
    316316        return self.mapping.get(self.tagtype, '')
    317317
     318class URLNode(Node):
     319    def __init__(self, view_name, args, kwargs):
     320        self.view_name = view_name
     321        self.args = args
     322        self.kwargs = kwargs
     323     
     324    def render(self, context):
     325        from django.core.urlresolvers import reverse, NoReverseMatch
     326        args = [arg.resolve(context) for arg in self.args]
     327        kwargs = dict([(k, v.resolve(context)) for k, v in self.kwargs.items()])
     328        try:
     329            return reverse(self.view_name, args=args, kwargs=kwargs)
     330        except NoReverseMatch:
     331            try:
     332                project_name = settings.SETTINGS_MODULE.split('.')[0]
     333                return reverse(project_name + '.' + self.view_name, args=args, kwargs=kwargs)
     334            except NoReverseMatch:
     335                return ''
     336
    318337class WidthRatioNode(Node):
    319338    def __init__(self, val_expr, max_expr, max_width):
    320339        self.val_expr = val_expr
     
    868887    return TemplateTagNode(tag)
    869888templatetag = register.tag(templatetag)
    870889
     890def url(parser, token):
     891    """
     892    Returns an absolute URL matching given view with its parameters. This is a mean to
     893    define links that aren't tied to a particular url configuration:
     894   
     895        {% url path.to.some_view arg1,arg2,name1=value1 %}
     896   
     897    The first argument is a path to a view. It can be an absolute python path or just
     898    ``app_name.view_name`` without the project name if the view is located inside the project.
     899    Other arguments are comma-separated values that will be filled in place of
     900    positional and keyword arguments in the URL. All arguments for the URL should be
     901    present.
     902   
     903    For example if you have a view ``app_name.client`` taking client's id and the
     904    corresponding line in a urlconf looks like this:
     905   
     906        ('^client/(\d+)/$', 'app_name.client')
     907   
     908    ... and this app's urlconf is included into the project's urlconf under some path:
     909   
     910        ('^clients/', include('project_name.app_name.urls'))
     911   
     912    ... then in a template you can create a link for a certain client like this:
     913   
     914        {% url app_name.client client.id %}
     915   
     916    The URL will look like ``/clients/client/123/``.
     917    """
     918    bits = token.contents.split(' ', 2)
     919    if len(bits) < 2:
     920        raise TemplateSyntaxError, "'%s' takes at least one argument (path to a view)" % bits[0]
     921    args = []
     922    kwargs = {}
     923    if len(bits) > 2:
     924        for arg in bits[2].split(','):
     925            if '=' in arg:
     926                k, v = arg.split('=', 1)
     927                kwargs[k] = parser.compile_filter(v)
     928            else:
     929                args.append(parser.compile_filter(arg))
     930    return URLNode(bits[1], args, kwargs)
     931url = register.tag(url)
     932
    871933#@register.tag
    872934def widthratio(parser, token):
    873935    """
  • tests/regressiontests/templates/tests.py

     
    620620            # Compare to a given parameter
    621621            'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=1), 'b':NOW - timedelta(days=2)}, '1 day'),
    622622            'timeuntil05' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=2), 'b':NOW - timedelta(days=2, minutes=1)}, '1 minute'),
     623
     624            ### URL TAG ########################################################
     625            # Successes
     626            'url01' : ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
     627            'url02' : ('{% url regressiontests.templates.views.client_action client.id,action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     628            'url03' : ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),
     629
     630            # Failures
     631            'url04' : ('{% url %}', {}, template.TemplateSyntaxError),
     632            'url05' : ('{% url no_such_view %}', {}, ''),
     633            'url06' : ('{% url regressiontests.templates.views.client no_such_param="value" %}', {}, ''),
    623634        }
    624635
    625636        # Register our custom template loader.
  • tests/urls.py

     
    77    # Always provide the auth system login and logout views
    88    (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
    99    (r'^accounts/logout/$', 'django.contrib.auth.views.login'),
     10   
     11    # test urlconf for {% url %} template tag
     12    (r'^url_tag/', include('regressiontests.templates.urls')),
    1013)
  • docs/templates.txt

     
    819819
    820820Note: ``opencomment`` and ``closecomment`` are new in the Django development version.
    821821
     822url
     823~~~
     824
     825Returns an absolute URL matching given view with its parameters. This is a mean to
     826define links that aren't tied to a particular url configuration:
     827
     828    {% url path.to.some_view arg1,arg2,name1=value1 %}
     829
     830The first argument is a path to a view. It can be an absolute python path or just
     831``app_name.view_name`` without the project name if the view is located inside the project.
     832Other arguments are comma-separated values that will be filled in place of
     833positional and keyword arguments in the URL. All arguments for the URL should be
     834present.
     835
     836For example if you have a view ``app_name.client`` taking client's id and the
     837corresponding line in a urlconf looks like this:
     838
     839    ('^client/(\d+)/$', 'app_name.client')
     840
     841... and this app's urlconf is included into the project's urlconf under some path:
     842
     843    ('^clients/', include('project_name.app_name.urls'))
     844
     845... then in a template you can create a link for a certain client like this:
     846
     847    {% url app_name.client client.id %}
     848
     849The URL will look like ``/clients/client/123/``.
     850
    822851widthratio
    823852~~~~~~~~~~
    824853
Back to Top