Ticket #12945: 12945.2.diff

File 12945.2.diff, 9.0 KB (added by Chris Beaven, 14 years ago)
  • django/template/defaulttags.py

    diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
    index 0db77f1..3ffd071 100644
    a b from django.utils.itercompat import groupby  
    1414from django.utils.safestring import mark_safe
    1515
    1616register = Library()
     17# Regex for token keyword arguments
     18kwarg_re = re.compile(r"(?:(\w+)=)?(.+)")
    1719
    1820class AutoEscapeControlNode(Node):
    1921    """Implements the actions of the autoescape tag."""
    def templatetag(parser, token):  
    10711073    return TemplateTagNode(tag)
    10721074templatetag = register.tag(templatetag)
    10731075
    1074 # Regex for URL arguments including filters
    1075 url_arg_re = re.compile(
    1076     r"(?:(%(name)s)=)?(%(value)s(?:\|%(name)s(?::%(value)s)?)*)" % {
    1077         'name':'\w+',
    1078         'value':'''(?:(?:'[^']*')|(?:"[^"]*")|(?:[\w\.-]+))'''},
    1079     re.VERBOSE)
     1076# Backwards compatibility check which will fail against for old comma
     1077# separated arguments in the url tag.
     1078url_backwards_re = re.compile(r'''(('[^']*'|"[^"]*"|[^,]+)=?)+$''')
    10801079
    10811080def url(parser, token):
    10821081    """
    def url(parser, token):  
    10851084    This is a way to define links that aren't tied to a particular URL
    10861085    configuration::
    10871086
    1088         {% url path.to.some_view arg1,arg2,name1=value1 %}
     1087        {% url path.to.some_view arg1 arg2 %}
     1088       
     1089        or
     1090       
     1091        {% url path.to.some_view name1=value1 name2=value2 %}
    10891092
    10901093    The first argument is a path to a view. It can be an absolute python path
    10911094    or just ``app_name.view_name`` without the project name if the view is
    def url(parser, token):  
    11171120    args = []
    11181121    kwargs = {}
    11191122    asvar = None
    1120 
    1121     if len(bits) > 2:
    1122         bits = iter(bits[2:])
     1123    bits = bits[2:]
     1124    if len(bits) >= 2 and bits[-2] == 'as':
     1125        asvar = bits[-1]
     1126        bits = bits[:-2]
     1127
     1128    # Backwards compatibility: {% url urlname arg1,arg2 %} or
     1129    # {% url urlname arg1,arg2 as foo %} cases.
     1130    if bits:
     1131        old_args = ''.join(bits)
     1132        if not url_backwards_re.match(old_args):
     1133            bits = old_args.split(",")
     1134
     1135    if len(bits):
    11231136        for bit in bits:
    1124             if bit == 'as':
    1125                 asvar = bits.next()
    1126                 break
     1137            match = kwarg_re.match(bit)
     1138            if not match:
     1139                raise TemplateSyntaxError("Malformed arguments to url tag")
     1140            name, value = match.groups()
     1141            if name:
     1142                kwargs[name] = parser.compile_filter(value)
    11271143            else:
    1128                 end = 0
    1129                 for i, match in enumerate(url_arg_re.finditer(bit)):
    1130                     if (i == 0 and match.start() != 0) or \
    1131                           (i > 0 and (bit[end:match.start()] != ',')):
    1132                         raise TemplateSyntaxError("Malformed arguments to url tag")
    1133                     end = match.end()
    1134                     name, value = match.group(1), match.group(2)
    1135                     if name:
    1136                         kwargs[name] = parser.compile_filter(value)
    1137                     else:
    1138                         args.append(parser.compile_filter(value))
    1139                 if end != len(bit):
    1140                     raise TemplateSyntaxError("Malformed arguments to url tag")
     1144                args.append(parser.compile_filter(value))
    11411145
    11421146    return URLNode(viewname, args, kwargs, asvar)
    11431147url = register.tag(url)
  • docs/ref/templates/builtins.txt

    diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
    index aabacc5..f015370 100644
    a b Returns an absolute URL (i.e., a URL without the domain name) matching a given  
    891891view function and optional parameters. This is a way to output links without
    892892violating the DRY principle by having to hard-code URLs in your templates::
    893893
    894     {% url path.to.some_view arg1,arg2,name1=value1 %}
     894    {% url path.to.some_view arg1 arg2 name1=value1 %}
    895895
    896896The first argument is a path to a view function in the format
    897897``package.package.module.function``. Additional arguments are optional and
    If you'd like to retrieve a URL without displaying it, you can use a slightly  
    935935different call::
    936936
    937937
    938     {% url path.to.view arg, arg2 as the_url %}
     938    {% url path.to.view arg arg2 as the_url %}
    939939
    940940    <a href="{{ the_url }}">I'm linking to {{ the_url }}</a>
    941941
    This will follow the normal :ref:`namespaced URL resolution strategy  
    957957<topics-http-reversing-url-namespaces>`, including using any hints provided
    958958by the context as to the current application.
    959959
     960.. versionchanged:: 1.2
     961
     962For backwards compatibility, the ``{% url %}`` tag supports the old syntax
     963from previous Django versions of comma separating the arguments. The previous
     964syntax does not support commas as part of string literals in the arguments.
     965
    960966.. templatetag:: widthratio
    961967
    962968widthratio
  • tests/regressiontests/templates/tests.py

    diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
    index 307fecc..2ae3146 100644
    a b class Templates(unittest.TestCase):  
    10201020
    10211021            ### URL TAG ########################################################
    10221022            # Successes
     1023            'legacyurl02': ('{% url regressiontests.templates.views.client_action id=client.id,action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1024            'legacyurl02a': ('{% url regressiontests.templates.views.client_action client.id,"update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1025            'legacyurl10': ('{% url regressiontests.templates.views.client_action id=client.id,action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
     1026            'legacyurl13': ('{% url regressiontests.templates.views.client_action id=client.id, action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
     1027            'legacyurl14': ('{% url regressiontests.templates.views.client_action client.id, arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
     1028
    10231029            'url01': ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
    1024             'url02': ('{% url regressiontests.templates.views.client_action id=client.id,action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
    1025             'url02a': ('{% url regressiontests.templates.views.client_action client.id,"update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1030            'url02': ('{% url regressiontests.templates.views.client_action id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1031            'url02a': ('{% url regressiontests.templates.views.client_action client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
    10261032            'url03': ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),
    10271033            'url04': ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
    10281034            'url05': (u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
    class Templates(unittest.TestCase):  
    10311037            'url08': (u'{% url метка_оператора v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
    10321038            'url09': (u'{% url метка_оператора_2 tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
    10331039            'url10': ('{% url regressiontests.templates.views.client_action id=client.id,action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
    1034             'url11': ('{% url regressiontests.templates.views.client_action id=client.id,action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),
    1035             'url12': ('{% url regressiontests.templates.views.client_action id=client.id,action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),
    1036             'url12': ('{% url regressiontests.templates.views.client_action id=client.id,action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
     1040            'url11': ('{% url regressiontests.templates.views.client_action id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),
     1041            'url12': ('{% url regressiontests.templates.views.client_action id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),
     1042            'url13': ('{% url regressiontests.templates.views.client_action id=client.id action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
     1043            'url14': ('{% url regressiontests.templates.views.client_action client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
     1044            'url15': ('{% url regressiontests.templates.views.client_action 12 "test" %}', {}, '/url_tag/client/12/test/'),
    10371045
    10381046            # Failures
    10391047            'url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
Back to Top