Ticket #14389: t14389-rc1.diff

File t14389-rc1.diff, 32.4 KB (added by russellm, 5 years ago)

RC1 of a patch fixing url and ssi template tags

  • django/template/defaulttags.py

    diff -r 9aed8047e568 django/template/defaulttags.py
    a b  
    290290    return False
    291291
    292292class SsiNode(Node):
    293     def __init__(self, filepath, parsed):
    294         self.filepath, self.parsed = filepath, parsed
     293    def __init__(self, filepath, parsed, legacy_filepath=True):
     294        self.filepath = filepath
     295        self.parsed = parsed
     296        self.legacy_filepath = legacy_filepath
    295297
    296298    def render(self, context):
    297         if not include_is_allowed(self.filepath):
     299        filepath = self.filepath
     300        if not self.legacy_filepath:
     301           filepath = filepath.resolve(context)
     302
     303        if not include_is_allowed(filepath):
    298304            if settings.DEBUG:
    299305                return "[Didn't have permission to include file]"
    300306            else:
    301307                return '' # Fail silently for invalid includes.
    302308        try:
    303             fp = open(self.filepath, 'r')
     309            fp = open(filepath, 'r')
    304310            output = fp.read()
    305311            fp.close()
    306312        except IOError:
    307313            output = ''
    308314        if self.parsed:
    309315            try:
    310                 t = Template(output, name=self.filepath)
     316                t = Template(output, name=filepath)
    311317                return t.render(context)
    312318            except TemplateSyntaxError, e:
    313319                if settings.DEBUG:
     
    356362        return self.mapping.get(self.tagtype, '')
    357363
    358364class URLNode(Node):
    359     def __init__(self, view_name, args, kwargs, asvar):
     365    def __init__(self, view_name, args, kwargs, asvar, legacy_view_name=True):
    360366        self.view_name = view_name
     367        self.legacy_view_name = legacy_view_name
    361368        self.args = args
    362369        self.kwargs = kwargs
    363370        self.asvar = asvar
     
    365372    def render(self, context):
    366373        from django.core.urlresolvers import reverse, NoReverseMatch
    367374        args = [arg.resolve(context) for arg in self.args]
    368         kwargs = dict([(smart_str(k,'ascii'), v.resolve(context))
     375        kwargs = dict([(smart_str(k, 'ascii'), v.resolve(context))
    369376                       for k, v in self.kwargs.items()])
    370377
     378        view_name = self.view_name
     379        if not self.legacy_view_name:
     380            view_name = view_name.resolve(context)
     381
    371382        # Try to look up the URL twice: once given the view name, and again
    372383        # relative to what we guess is the "main" app. If they both fail,
    373384        # re-raise the NoReverseMatch unless we're using the
    374385        # {% url ... as var %} construct in which cause return nothing.
    375386        url = ''
    376387        try:
    377             url = reverse(self.view_name, args=args, kwargs=kwargs, current_app=context.current_app)
     388            url = reverse(view_name, args=args, kwargs=kwargs, current_app=context.current_app)
    378389        except NoReverseMatch, e:
    379390            if settings.SETTINGS_MODULE:
    380391                project_name = settings.SETTINGS_MODULE.split('.')[0]
    381392                try:
    382                     url = reverse(project_name + '.' + self.view_name,
    383                               args=args, kwargs=kwargs, current_app=context.current_app)
     393                    url = reverse(project_name + '.' + view_name,
     394                              args=args, kwargs=kwargs,
     395                              current_app=context.current_app)
    384396                except NoReverseMatch:
    385397                    if self.asvar is None:
    386398                        # Re-raise the original exception, not the one with
     
    922934
    923935        {% ssi /home/html/ljworld.com/includes/right_generic.html parsed %}
    924936    """
     937
     938    import warnings
     939    warnings.warn('The syntax for the ssi template tag is changing. Load the future_ssi tag library to start using the new behavior.',
     940                  category=PendingDeprecationWarning)
     941
    925942    bits = token.contents.split()
    926943    parsed = False
    927944    if len(bits) not in (2, 3):
     
    933950        else:
    934951            raise TemplateSyntaxError("Second (optional) argument to %s tag"
    935952                                      " must be 'parsed'" % bits[0])
    936     return SsiNode(bits[1], parsed)
     953    return SsiNode(bits[1], parsed, legacy_filepath=True)
    937954ssi = register.tag(ssi)
    938955
    939956#@register.tag
     
    11401157
    11411158    The URL will look like ``/clients/client/123/``.
    11421159    """
     1160
     1161    import warnings
     1162    warnings.warn('The syntax for the url template tag is changing. Load the future_url tag library to start using the new behavior.',
     1163                  category=PendingDeprecationWarning)
     1164
    11431165    bits = token.split_contents()
    11441166    if len(bits) < 2:
    11451167        raise TemplateSyntaxError("'%s' takes at least one argument"
     
    11961218            else:
    11971219                args.append(parser.compile_filter(value))
    11981220
    1199     return URLNode(viewname, args, kwargs, asvar)
     1221    return URLNode(viewname, args, kwargs, asvar, legacy_view_name=True)
    12001222url = register.tag(url)
    12011223
    12021224#@register.tag
  • new file django/templatetags/future_ssi.py

    diff -r 9aed8047e568 django/templatetags/future_ssi.py
    - +  
     1from django.conf import settings
     2from django.template import Library, Node, Template, TemplateSyntaxError
     3from django.template.defaulttags import include_is_allowed, SsiNode
     4
     5
     6register = Library()
     7
     8@register.tag
     9def ssi(parser, token):
     10    """
     11    Outputs the contents of a given file into the page.
     12
     13    Like a simple "include" tag, the ``ssi`` tag includes the contents
     14    of another file -- which must be specified using an absolute path --
     15    in the current page::
     16
     17        {% ssi "/home/html/ljworld.com/includes/right_generic.html" %}
     18
     19    If the optional "parsed" parameter is given, the contents of the included
     20    file are evaluated as template code, with the current context::
     21
     22        {% ssi "/home/html/ljworld.com/includes/right_generic.html" parsed %}
     23    """
     24    bits = token.contents.split()
     25    parsed = False
     26    if len(bits) not in (2, 3):
     27        raise TemplateSyntaxError("'ssi' tag takes one argument: the path to"
     28                                  " the file to be included")
     29    if len(bits) == 3:
     30        if bits[2] == 'parsed':
     31            parsed = True
     32        else:
     33            raise TemplateSyntaxError("Second (optional) argument to %s tag"
     34                                      " must be 'parsed'" % bits[0])
     35    filepath = parser.compile_filter(bits[1])
     36    return SsiNode(filepath, parsed, legacy_filepath=False)
     37
  • new file django/templatetags/future_url.py

    diff -r 9aed8047e568 django/templatetags/future_url.py
    - +  
     1from django.conf import settings
     2from django.template import Library, Node, TemplateSyntaxError
     3from django.template.defaulttags import kwarg_re, URLNode
     4from django.utils.encoding import smart_str
     5
     6
     7register = Library()
     8
     9@register.tag
     10def url(parser, token):
     11    """
     12    Returns an absolute URL matching given view with its parameters.
     13
     14    This is a way to define links that aren't tied to a particular URL
     15    configuration::
     16
     17        {% url "path.to.some_view" arg1 arg2 %}
     18
     19        or
     20
     21        {% url "path.to.some_view" name1=value1 name2=value2 %}
     22
     23    The first argument is a path to a view. It can be an absolute python path
     24    or just ``app_name.view_name`` without the project name if the view is
     25    located inside the project.  Other arguments are comma-separated values
     26    that will be filled in place of positional and keyword arguments in the
     27    URL. All arguments for the URL should be present.
     28
     29    For example if you have a view ``app_name.client`` taking client's id and
     30    the corresponding line in a URLconf looks like this::
     31
     32        ('^client/(\d+)/$', 'app_name.client')
     33
     34    and this app's URLconf is included into the project's URLconf under some
     35    path::
     36
     37        ('^clients/', include('project_name.app_name.urls'))
     38
     39    then in a template you can create a link for a certain client like this::
     40
     41        {% url "app_name.client" client.id %}
     42
     43    The URL will look like ``/clients/client/123/``.
     44    """
     45    bits = token.split_contents()
     46    if len(bits) < 2:
     47        raise TemplateSyntaxError("'%s' takes at least one argument"
     48                                  " (path to a view)" % bits[0])
     49    viewname = parser.compile_filter(bits[1])
     50    args = []
     51    kwargs = {}
     52    asvar = None
     53    bits = bits[2:]
     54    if len(bits) >= 2 and bits[-2] == 'as':
     55        asvar = bits[-1]
     56        bits = bits[:-2]
     57
     58    if len(bits):
     59        for bit in bits:
     60            match = kwarg_re.match(bit)
     61            if not match:
     62                raise TemplateSyntaxError("Malformed arguments to url tag")
     63            name, value = match.groups()
     64            if name:
     65                kwargs[name] = parser.compile_filter(value)
     66            else:
     67                args.append(parser.compile_filter(value))
     68
     69    return URLNode(viewname, args, kwargs, asvar, legacy_view_name=False)
     70
  • docs/internals/deprecation.txt

    diff -r 9aed8047e568 docs/internals/deprecation.txt
    a b  
    131131          been deprecated in favor of the
    132132          :class:`~django.contrib.staticfiles.handlers.StaticFilesHandler`.
    133133
     134        * The :ttag:`url` and :ttag:`ssi` template tags will be modified so that
     135          the first argument to each tag is a template variable, not an implied
     136          string. The new-style behavior is provided with the ``future_url`` and
     137          ``future_ssi`` template tag libraries.
     138
    134139    * 2.0
    135140        * ``django.views.defaults.shortcut()``. This function has been moved
    136141          to ``django.contrib.contenttypes.views.shortcut()`` as part of the
  • docs/ref/templates/builtins.txt

    diff -r 9aed8047e568 docs/ref/templates/builtins.txt
    a b  
    838838
    839839See also: ``{% include %}``.
    840840
     841.. admonition:: Forwards compatibility
     842
     843    .. versionchanged:: 1.3
     844
     845    In Django 1.5, the behavior of the :ttag:`ssi` template tag will
     846    change, with the the first argument being made into a context
     847    variable, rather than being a special case unquoted constant. This
     848    will allow the :ttag:`ssi` tag to use a context variable as the
     849    value of the page to be included.
     850
     851    In order to provide a forwards compatibility path, Django 1.3
     852    provides a compatibility library -- ``future_ssi`` -- that
     853    implements the new behavior. To use this library, add a
     854    :ttag:`load` call at the top of any template using the :ttag:`ssi`
     855    tag, and wrap the first argument to the :ttag:`ssi` tag in quotes.
     856    For example::
     857
     858        {% load future_ssi %}
     859        {% ssi '/home/html/ljworld.com/includes/right_generic.html' %}
     860
     861    In Django 1.5, the unquoted constant behavior will be replaced
     862    with the behavior provided by the ``future_ssi`` tag library.
     863    Existing templates be migrated to use the new syntax.
     864
    841865.. templatetag:: templatetag
    842866
    843867templatetag
     
    955979    {% url path.to.view arg,arg2 %}
    956980    {% url path.to.view arg, arg2 %}
    957981
    958 This syntax doesn't support the use of literal commas, or or equals
     982This syntax doesn't support the use of literal commas, or equals
    959983signs. Did we mention you shouldn't use this syntax in any new
    960984projects?
    961985
     986.. admonition:: Forwards compatibility
     987
     988    .. versionchanged:: 1.3
     989
     990    In Django 1.5, the behavior of the :ttag:`url` template tag will
     991    change, with the the first argument being made into a context
     992    variable, rather than being a special case unquoted constant. This
     993    will allow the :ttag:`url` tag to use a context variable as the
     994    value of the URL name to be reversed.
     995
     996    In order to provide a forwards compatibility path, Django 1.3
     997    provides a compatibility library -- ``future_url`` -- that
     998    implements the new behavior. To use this library, add a
     999    :ttag:`load` call at the top of any template using the :ttag:`url`
     1000    tag, and wrap the first argument to the :ttag:`url` tag in quotes.
     1001    For example::
     1002
     1003        {% load future_url %}
     1004        {% url 'myapp:view-name' %}
     1005
     1006    The new library also formally deprecates the comma syntax for
     1007    separating arguments to the :ttag:`url` template tag.
     1008
     1009    In Django 1.5, the old behavior will be replaced with the behavior
     1010    provided by the ``future_url`` tag library. Existing templates be
     1011    migrated to use the new syntax.
     1012
    9621013.. templatetag:: widthratio
    9631014
    9641015widthratio
  • docs/releases/1.3.txt

    diff -r 9aed8047e568 docs/releases/1.3.txt
    a b  
    341341redundancy, :class:`~django.test.simple.DjangoTestRunner` has been
    342342turned into an empty placeholder class, and will be removed entirely
    343343in Django 1.5.
     344
     345Changes to :ttag:`url` and :ttag:`ssi`
     346~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     347
     348inconsistency. Most template tags will allow you to pass in either
     349constants or variables as arguments -- for example::
     350
     351    {% extends "base.html" %}
     352
     353allows you to specify a base template as a constant, but if you have a
     354context variable ``templ`` that contains the value ``base.html``::
     355
     356    {% extends templ %}
     357
     358is also legal.
     359
     360However, due to an accident of history, the :ttag:`url` and
     361:ttag:`ssi` are different. These tags use the second, quoteless
     362syntax, but interpret the argument as a constant. This means it isn't
     363possible to use a context variable as the target of a :ttag:`url` and
     364:ttag:`ssi` tag.
     365
     366Django 1.3 marks the start of the process to correct this historical
     367accident. Django 1.3 adds two new template libraries -- ``future_url``
     368and ``future_ssi`` -- which provide alternate implementations of the
     369:ttag:`url` and :ttag:`ssi` template tags. These ``future`` libraries
     370implement behavior that makes the handling of the first argument
     371consistent with the handling of all other variables. So, an existing
     372template that contains::
     373
     374    {% url sample %}
     375
     376should be replaced with::
     377
     378    {% load future_url %}
     379    {% url 'sample' %}
     380
     381The tags implementing the old behavior have been deprecated, and in
     382Django 1.5, the old behavior will be replaced with the new behavior.
     383To ensure compatibility with future versions of Django, existing
     384templates should be modified to use the new ``future`` libraries and
     385syntax.
  • new file tests/regressiontests/templates/templates/ssi_include.html

    diff -r 9aed8047e568 tests/regressiontests/templates/templates/ssi_include.html
    - +  
     1This is for testing an ssi include. {{ test }}
  • tests/regressiontests/templates/tests.py

    diff -r 9aed8047e568 tests/regressiontests/templates/tests.py
    a b  
    354354        old_invalid = settings.TEMPLATE_STRING_IF_INVALID
    355355        expected_invalid_str = 'INVALID'
    356356
     357        #Set ALLOWED_INCLUDE_ROOTS so that ssi works.
     358        old_allowed_include_roots = settings.ALLOWED_INCLUDE_ROOTS
     359        settings.ALLOWED_INCLUDE_ROOTS = os.path.dirname(os.path.abspath(__file__))
     360
    357361        # Warm the URL reversing cache. This ensures we don't pay the cost
    358362        # warming the cache during one of the tests.
    359363        urlresolvers.reverse('regressiontests.templates.views.client_action',
     
    416420        deactivate()
    417421        settings.TEMPLATE_DEBUG = old_td
    418422        settings.TEMPLATE_STRING_IF_INVALID = old_invalid
     423        settings.ALLOWED_INCLUDE_ROOTS = old_allowed_include_roots
    419424
    420425        self.assertEqual(failures, [], "Tests failed:\n%s\n%s" %
    421426            ('-'*70, ("\n%s\n" % ('-'*70)).join(failures)))
     
    11791184                          '{% endfor %},' + \
    11801185                          '{% endfor %}',
    11811186                          {}, ''),
     1187            ### SSI TAG ########################################################
     1188
     1189            # Test normal behavior
     1190            'old-ssi01': ('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'),
     1191            'old-ssi02': ('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''),
     1192
     1193            # Test parsed output
     1194            'old-ssi06': ('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'),
     1195            'old-ssi07': ('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {'test': 'Look ma! It parsed!'}, ''),
     1196
     1197            # Future compatibility
     1198            # Test normal behavior
     1199            'ssi01': ('{%% load future_ssi %%}{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'),
     1200            'ssi02': ('{%% load future_ssi %%}{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''),
     1201            'ssi03': ("{%% load future_ssi %%}{%% ssi '%s' %%}" % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''),
     1202
     1203            # Test passing as a variable
     1204            'ssi04': ('{% load future_ssi %}{% ssi ssi_file %}', {'ssi_file': os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html')}, 'This is for testing an ssi include. {{ test }}\n'),
     1205            'ssi05': ('{% load future_ssi %}{% ssi ssi_file %}', {'ssi_file': 'no_file'}, ''),
     1206
     1207            # Test parsed output
     1208            'ssi06': ('{%% load future_ssi %%}{%% ssi "%s" parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'),
     1209            'ssi07': ('{%% load future_ssi %%}{%% ssi "%s" parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {'test': 'Look ma! It parsed!'}, ''),
     1210
    11821211
    11831212            ### TEMPLATETAG TAG #######################################################
    11841213            'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
     
    12441273            'legacyurl16a': ("{% url regressiontests.templates.views.client_action action='update',id='1' %}", {}, '/url_tag/client/1/update/'),
    12451274            'legacyurl17': ('{% url regressiontests.templates.views.client_action client_id=client.my_id,action=action %}', {'client': {'my_id': 1}, 'action': 'update'}, '/url_tag/client/1/update/'),
    12461275
    1247             'url01': ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
    1248             'url02': ('{% url regressiontests.templates.views.client_action id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
    1249             'url02a': ('{% url regressiontests.templates.views.client_action client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
    1250             'url02b': ("{% url regressiontests.templates.views.client_action id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
    1251             'url02c': ("{% url regressiontests.templates.views.client_action client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
    1252             'url03': ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),
    1253             'url04': ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
    1254             'url05': (u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
    1255             'url06': (u'{% url метка_оператора_2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
    1256             'url07': (u'{% url regressiontests.templates.views.client2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
    1257             'url08': (u'{% url метка_оператора v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
    1258             'url09': (u'{% url метка_оператора_2 tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
    1259             'url10': ('{% url regressiontests.templates.views.client_action id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
    1260             'url11': ('{% url regressiontests.templates.views.client_action id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),
    1261             'url12': ('{% url regressiontests.templates.views.client_action id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),
    1262             '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/'),
    1263             'url14': ('{% url regressiontests.templates.views.client_action client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
    1264             'url15': ('{% url regressiontests.templates.views.client_action 12 "test" %}', {}, '/url_tag/client/12/test/'),
    1265             'url18': ('{% url regressiontests.templates.views.client "1,2" %}', {}, '/url_tag/client/1,2/'),
     1276            'old-url01': ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
     1277            'old-url02': ('{% url regressiontests.templates.views.client_action id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1278            'old-url02a': ('{% url regressiontests.templates.views.client_action client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1279            'old-url02b': ("{% url regressiontests.templates.views.client_action id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1280            'old-url02c': ("{% url regressiontests.templates.views.client_action client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1281            'old-url03': ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),
     1282            'old-url04': ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
     1283            'old-url05': (u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1284            'old-url06': (u'{% url метка_оператора_2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1285            'old-url07': (u'{% url regressiontests.templates.views.client2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1286            'old-url08': (u'{% url метка_оператора v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1287            'old-url09': (u'{% url метка_оператора_2 tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1288            'old-url10': ('{% url regressiontests.templates.views.client_action id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
     1289            'old-url11': ('{% url regressiontests.templates.views.client_action id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),
     1290            'old-url12': ('{% url regressiontests.templates.views.client_action id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),
     1291            'old-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/'),
     1292            'old-url14': ('{% url regressiontests.templates.views.client_action client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
     1293            'old-url15': ('{% url regressiontests.templates.views.client_action 12 "test" %}', {}, '/url_tag/client/12/test/'),
     1294            'old-url18': ('{% url regressiontests.templates.views.client "1,2" %}', {}, '/url_tag/client/1,2/'),
    12661295
    12671296            # Failures
    1268             'url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
    1269             'url-fail02': ('{% url no_such_view %}', {}, urlresolvers.NoReverseMatch),
    1270             'url-fail03': ('{% url regressiontests.templates.views.client %}', {}, urlresolvers.NoReverseMatch),
    1271             'url-fail04': ('{% url view id, %}', {}, template.TemplateSyntaxError),
    1272             'url-fail05': ('{% url view id= %}', {}, template.TemplateSyntaxError),
    1273             'url-fail06': ('{% url view a.id=id %}', {}, template.TemplateSyntaxError),
    1274             'url-fail07': ('{% url view a.id!id %}', {}, template.TemplateSyntaxError),
    1275             'url-fail08': ('{% url view id="unterminatedstring %}', {}, template.TemplateSyntaxError),
    1276             'url-fail09': ('{% url view id=", %}', {}, template.TemplateSyntaxError),
     1297            'old-url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
     1298            'old-url-fail02': ('{% url no_such_view %}', {}, urlresolvers.NoReverseMatch),
     1299            'old-url-fail03': ('{% url regressiontests.templates.views.client %}', {}, urlresolvers.NoReverseMatch),
     1300            'old-url-fail04': ('{% url view id, %}', {}, template.TemplateSyntaxError),
     1301            'old-url-fail05': ('{% url view id= %}', {}, template.TemplateSyntaxError),
     1302            'old-url-fail06': ('{% url view a.id=id %}', {}, template.TemplateSyntaxError),
     1303            'old-url-fail07': ('{% url view a.id!id %}', {}, template.TemplateSyntaxError),
     1304            'old-url-fail08': ('{% url view id="unterminatedstring %}', {}, template.TemplateSyntaxError),
     1305            'old-url-fail09': ('{% url view id=", %}', {}, template.TemplateSyntaxError),
    12771306
    12781307            # {% url ... as var %}
    1279             'url-asvar01': ('{% url regressiontests.templates.views.index as url %}', {}, ''),
    1280             'url-asvar02': ('{% url regressiontests.templates.views.index as url %}{{ url }}', {}, '/url_tag/'),
    1281             'url-asvar03': ('{% url no_such_view as url %}{{ url }}', {}, ''),
     1308            'old-url-asvar01': ('{% url regressiontests.templates.views.index as url %}', {}, ''),
     1309            'old-url-asvar02': ('{% url regressiontests.templates.views.index as url %}{{ url }}', {}, '/url_tag/'),
     1310            'old-url-asvar03': ('{% url no_such_view as url %}{{ url }}', {}, ''),
     1311
     1312            # forward compatibility
     1313            # Successes
     1314            'url01': ('{% load future_url %}{% url "regressiontests.templates.views.client" client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
     1315            'url02': ('{% load future_url %}{% url "regressiontests.templates.views.client_action" id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1316            'url02a': ('{% load future_url %}{% url "regressiontests.templates.views.client_action" client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1317            'url02b': ("{% load future_url %}{% url 'regressiontests.templates.views.client_action' id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1318            'url02c': ("{% load future_url %}{% url 'regressiontests.templates.views.client_action' client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
     1319            'url03': ('{% load future_url %}{% url "regressiontests.templates.views.index" %}', {}, '/url_tag/'),
     1320            'url04': ('{% load future_url %}{% url "named.client" client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
     1321            'url05': (u'{% load future_url %}{% url "метка_оператора" v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1322            'url06': (u'{% load future_url %}{% url "метка_оператора_2" tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1323            'url07': (u'{% load future_url %}{% url "regressiontests.templates.views.client2" tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1324            'url08': (u'{% load future_url %}{% url "метка_оператора" v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1325            'url09': (u'{% load future_url %}{% url "метка_оператора_2" tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
     1326            'url10': ('{% load future_url %}{% url "regressiontests.templates.views.client_action" id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
     1327            'url11': ('{% load future_url %}{% url "regressiontests.templates.views.client_action" id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),
     1328            'url12': ('{% load future_url %}{% url "regressiontests.templates.views.client_action" id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),
     1329            'url13': ('{% load future_url %}{% url "regressiontests.templates.views.client_action" id=client.id action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
     1330            'url14': ('{% load future_url %}{% url "regressiontests.templates.views.client_action" client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
     1331            'url15': ('{% load future_url %}{% url "regressiontests.templates.views.client_action" 12 "test" %}', {}, '/url_tag/client/12/test/'),
     1332            'url18': ('{% load future_url %}{% url "regressiontests.templates.views.client" "1,2" %}', {}, '/url_tag/client/1,2/'),
     1333
     1334            'url19': ('{% load future_url %}{% url named_url client.id %}', {'named_url': 'regressiontests.templates.views.client', 'client': {'id': 1}}, '/url_tag/client/1/'),
     1335
     1336            # Failures
     1337            'url-fail01': ('{% load future_url %}{% url %}', {}, template.TemplateSyntaxError),
     1338            'url-fail02': ('{% load future_url %}{% url "no_such_view" %}', {}, urlresolvers.NoReverseMatch),
     1339            'url-fail03': ('{% load future_url %}{% url "regressiontests.templates.views.client" %}', {}, urlresolvers.NoReverseMatch),
     1340            'url-fail04': ('{% load future_url %}{% url "view" id, %}', {}, template.TemplateSyntaxError),
     1341            'url-fail05': ('{% load future_url %}{% url "view" id= %}', {}, template.TemplateSyntaxError),
     1342            'url-fail06': ('{% load future_url %}{% url "view" a.id=id %}', {}, template.TemplateSyntaxError),
     1343            'url-fail07': ('{% load future_url %}{% url "view" a.id!id %}', {}, template.TemplateSyntaxError),
     1344            'url-fail08': ('{% load future_url %}{% url "view" id="unterminatedstring %}', {}, template.TemplateSyntaxError),
     1345            'url-fail09': ('{% load future_url %}{% url "view" id=", %}', {}, template.TemplateSyntaxError),
     1346
     1347            'url-fail11': ('{% load future_url %}{% url named_url %}', {}, urlresolvers.NoReverseMatch),
     1348            'url-fail12': ('{% load future_url %}{% url named_url %}', {'named_url': 'no_such_view'}, urlresolvers.NoReverseMatch),
     1349            'url-fail13': ('{% load future_url %}{% url named_url %}', {'named_url': 'regressiontests.templates.views.client'}, urlresolvers.NoReverseMatch),
     1350            'url-fail14': ('{% load future_url %}{% url named_url id, %}', {'named_url': 'view'}, template.TemplateSyntaxError),
     1351            'url-fail15': ('{% load future_url %}{% url named_url id= %}', {'named_url': 'view'}, template.TemplateSyntaxError),
     1352            'url-fail16': ('{% load future_url %}{% url named_url a.id=id %}', {'named_url': 'view'}, template.TemplateSyntaxError),
     1353            'url-fail17': ('{% load future_url %}{% url named_url a.id!id %}', {'named_url': 'view'}, template.TemplateSyntaxError),
     1354            'url-fail18': ('{% load future_url %}{% url named_url id="unterminatedstring %}', {'named_url': 'view'}, template.TemplateSyntaxError),
     1355            'url-fail19': ('{% load future_url %}{% url named_url id=", %}', {'named_url': 'view'}, template.TemplateSyntaxError),
     1356
     1357            # {% url ... as var %}
     1358            'url-asvar01': ('{% load future_url %}{% url "regressiontests.templates.views.index" as url %}', {}, ''),
     1359            'url-asvar02': ('{% load future_url %}{% url "regressiontests.templates.views.index" as url %}{{ url }}', {}, '/url_tag/'),
     1360            'url-asvar03': ('{% load future_url %}{% url "no_such_view" as url %}{{ url }}', {}, ''),
    12821361
    12831362            ### CACHE TAG ######################################################
    12841363            'cache01': ('{% load cache %}{% cache -1 test %}cache01{% endcache %}', {}, 'cache01'),
Back to Top