Fixed #18037 -- Changed behaviour of url and ssi template tags to the new syntax, as per official deprecation timeline. Thanks Ramiro Morales and Jannis Leidel for the review.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17934 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Claude Paroz 2012-04-24 19:55:52 +00:00
parent c4e62eff90
commit eb351ac9cb
41 changed files with 132 additions and 439 deletions

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/index.html" %}
{% load i18n %}
{% load url from future %}
{% if not is_popup %}
{% block breadcrumbs %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static admin_modify %}
{% load url from future %}
{% load admin_urls %}
{% block extrahead %}{{ block.super }}

View File

@ -1,4 +1,4 @@
{% load admin_static %}{% load url from future %}<!DOCTYPE html>
{% load admin_static %}<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head>
<title>{% block title %}{% endblock %}</title>

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static admin_modify %}
{% load url from future %}
{% load admin_urls %}
{% block extrahead %}{{ block.super }}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static admin_list %}
{% load url from future %}
{% load admin_urls %}
{% block extrastyle %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% load admin_urls %}
{% block breadcrumbs %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n l10n %}
{% load url from future %}
{% load admin_urls %}
{% block breadcrumbs %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
{% load url from future %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/login.css" %}" />{% endblock %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% load admin_urls %}
{% block breadcrumbs %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="{% url 'admin:index' %}">{% trans 'Home' %}</a></div>{% endblock %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block userlinks %}{% url 'django-admindocs-docroot' as docsroot %}{% if docsroot %}<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> / {% endif %}{% trans 'Change password' %} / <a href="{% url 'admin:logout' %}">{% trans 'Log out' %}</a>{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% load url from future %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
{% block userlinks %}{% url 'django-admindocs-docroot' as docsroot %}{% if docsroot %}<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> / {% endif %} {% trans 'Change password' %} / <a href="{% url 'admin:logout' %}">{% trans 'Log out' %}</a>{% endblock %}
{% block breadcrumbs %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,4 +1,4 @@
{% load i18n %}{% load url from future %}{% autoescape off %}
{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this e-mail because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page and choose a new password:" %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block extrahead %}
{{ block.super }}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block coltype %}colSM{% endblock %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block coltype %}colSM{% endblock %}
{% block breadcrumbs %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block coltype %}colSM{% endblock %}
{% block breadcrumbs %}

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcrumbs %}
<div class="breadcrumbs">

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load url from future %}
{% block coltype %}colSM{% endblock %}
{% block breadcrumbs %}

View File

@ -1,4 +1,4 @@
{% load url from future %}unicode: {{ user }}
unicode: {{ user }}
id: {{ user.id }}
username: {{ user.username }}
url: {% url 'userpage' user %}

View File

@ -315,15 +315,12 @@ def include_is_allowed(filepath):
return False
class SsiNode(Node):
def __init__(self, filepath, parsed, legacy_filepath=True):
def __init__(self, filepath, parsed):
self.filepath = filepath
self.parsed = parsed
self.legacy_filepath = legacy_filepath
def render(self, context):
filepath = self.filepath
if not self.legacy_filepath:
filepath = filepath.resolve(context)
filepath = self.filepath.resolve(context)
if not include_is_allowed(filepath):
if settings.DEBUG:
@ -385,9 +382,8 @@ class TemplateTagNode(Node):
return self.mapping.get(self.tagtype, '')
class URLNode(Node):
def __init__(self, view_name, args, kwargs, asvar, legacy_view_name=True):
def __init__(self, view_name, args, kwargs, asvar):
self.view_name = view_name
self.legacy_view_name = legacy_view_name
self.args = args
self.kwargs = kwargs
self.asvar = asvar
@ -398,9 +394,7 @@ class URLNode(Node):
kwargs = dict([(smart_str(k, 'ascii'), v.resolve(context))
for k, v in self.kwargs.items()])
view_name = self.view_name
if not self.legacy_view_name:
view_name = view_name.resolve(context)
view_name = self.view_name.resolve(context)
# 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,
@ -969,19 +963,14 @@ def ssi(parser, token):
of another file -- which must be specified using an absolute path --
in the current page::
{% ssi /home/html/ljworld.com/includes/right_generic.html %}
{% ssi "/home/html/ljworld.com/includes/right_generic.html" %}
If the optional "parsed" parameter is given, the contents of the included
file are evaluated as template code, with the current context::
{% ssi /home/html/ljworld.com/includes/right_generic.html parsed %}
{% ssi "/home/html/ljworld.com/includes/right_generic.html" parsed %}
"""
import warnings
warnings.warn('The syntax for the ssi template tag is changing. Load the `ssi` tag from the `future` tag library to start using the new behavior.',
category=DeprecationWarning)
bits = token.contents.split()
bits = token.split_contents()
parsed = False
if len(bits) not in (2, 3):
raise TemplateSyntaxError("'ssi' tag takes one argument: the path to"
@ -992,7 +981,8 @@ def ssi(parser, token):
else:
raise TemplateSyntaxError("Second (optional) argument to %s tag"
" must be 'parsed'" % bits[0])
return SsiNode(bits[1], parsed, legacy_filepath=True)
filepath = parser.compile_filter(bits[1])
return SsiNode(filepath, parsed)
@register.tag
def load(parser, token):
@ -1201,17 +1191,21 @@ def url(parser, token):
This is a way to define links that aren't tied to a particular URL
configuration::
{% url path.to.some_view arg1 arg2 %}
{% url "path.to.some_view" arg1 arg2 %}
or
{% url path.to.some_view name1=value1 name2=value2 %}
{% url "path.to.some_view" name1=value1 name2=value2 %}
The first argument is a path to a view. It can be an absolute python path
The first argument is a path to a view. It can be an absolute Python path
or just ``app_name.view_name`` without the project name if the view is
located inside the project. Other arguments are comma-separated values
that will be filled in place of positional and keyword arguments in the
URL. All arguments for the URL should be present.
located inside the project.
Other arguments are space-separated values that will be filled in place of
positional and keyword arguments in the URL. Don't mix positional and
keyword arguments.
All arguments for the URL should be present.
For example if you have a view ``app_name.client`` taking client's id and
the corresponding line in a URLconf looks like this::
@ -1225,20 +1219,39 @@ def url(parser, token):
then in a template you can create a link for a certain client like this::
{% url app_name.client client.id %}
{% url "app_name.client" client.id %}
The URL will look like ``/clients/client/123/``.
The first argument can also be a named URL instead of the Python path to
the view callable. For example if the URLconf entry looks like this::
url('^client/(\d+)/$', name='client-detail-view')
then in the template you can use::
{% url "client-detail-view" client.id %}
There is even another possible value type for the first argument. It can be
the name of a template variable that will be evaluated to obtain the view
name or the URL name, e.g.::
{% with view_path="app_name.client" %}
{% url view_path client.id %}
{% endwith %}
or,
{% with url_name="client-detail-view" %}
{% url url_name client.id %}
{% endwith %}
"""
import warnings
warnings.warn('The syntax for the url template tag is changing. Load the `url` tag from the `future` tag library to start using the new behavior.',
category=DeprecationWarning)
bits = token.split_contents()
if len(bits) < 2:
raise TemplateSyntaxError("'%s' takes at least one argument"
" (path to a view)" % bits[0])
viewname = bits[1]
viewname = parser.compile_filter(bits[1])
args = []
kwargs = {}
asvar = None
@ -1247,38 +1260,6 @@ def url(parser, token):
asvar = bits[-1]
bits = bits[:-2]
# Backwards compatibility: check for the old comma separated format
# {% url urlname arg1,arg2 %}
# Initial check - that the first space separated bit has a comma in it
if bits and ',' in bits[0]:
check_old_format = True
# In order to *really* be old format, there must be a comma
# in *every* space separated bit, except the last.
for bit in bits[1:-1]:
if ',' not in bit:
# No comma in this bit. Either the comma we found
# in bit 1 was a false positive (e.g., comma in a string),
# or there is a syntax problem with missing commas
check_old_format = False
break
else:
# No comma found - must be new format.
check_old_format = False
if check_old_format:
# Confirm that this is old format by trying to parse the first
# argument. An exception will be raised if the comma is
# unexpected (i.e. outside of a static string).
match = kwarg_re.match(bits[0])
if match:
value = match.groups()[1]
try:
parser.compile_filter(value)
except TemplateSyntaxError:
bits = ''.join(bits).split(',')
# Now all the bits are parsed into new format,
# process them as template vars
if len(bits):
for bit in bits:
match = kwarg_re.match(bit)
@ -1290,7 +1271,7 @@ def url(parser, token):
else:
args.append(parser.compile_filter(value))
return URLNode(viewname, args, kwargs, asvar, legacy_view_name=True)
return URLNode(viewname, args, kwargs, asvar)
@register.tag
def widthratio(parser, token):

View File

@ -1,124 +1,14 @@
from django.template import Library, TemplateSyntaxError
from django.template.defaulttags import kwarg_re, SsiNode, URLNode
from django.template import Library
from django.template.defaulttags import url as default_url, ssi as default_ssi
register = Library()
@register.tag
def ssi(parser, token):
"""
Outputs the contents of a given file into the page.
Like a simple "include" tag, the ``ssi`` tag includes the contents
of another file -- which must be specified using an absolute path --
in the current page::
{% ssi "/home/html/ljworld.com/includes/right_generic.html" %}
If the optional "parsed" parameter is given, the contents of the included
file are evaluated as template code, with the current context::
{% ssi "/home/html/ljworld.com/includes/right_generic.html" parsed %}
"""
bits = token.split_contents()
parsed = False
if len(bits) not in (2, 3):
raise TemplateSyntaxError("'ssi' tag takes one argument: the path to"
" the file to be included")
if len(bits) == 3:
if bits[2] == 'parsed':
parsed = True
else:
raise TemplateSyntaxError("Second (optional) argument to %s tag"
" must be 'parsed'" % bits[0])
filepath = parser.compile_filter(bits[1])
return SsiNode(filepath, parsed, legacy_filepath=False)
# Used for deprecation path during 1.3/1.4, will be removed in 2.0
return default_ssi(parser, token)
@register.tag
def url(parser, token):
"""
Returns an absolute URL matching given view with its parameters.
This is a way to define links that aren't tied to a particular URL
configuration::
{% url "path.to.some_view" arg1 arg2 %}
or
{% url "path.to.some_view" name1=value1 name2=value2 %}
The first argument is a path to a view. It can be an absolute Python path
or just ``app_name.view_name`` without the project name if the view is
located inside the project.
Other arguments are space-separated values that will be filled in place of
positional and keyword arguments in the URL. Don't mix positional and
keyword arguments.
All arguments for the URL should be present.
For example if you have a view ``app_name.client`` taking client's id and
the corresponding line in a URLconf looks like this::
('^client/(\d+)/$', 'app_name.client')
and this app's URLconf is included into the project's URLconf under some
path::
('^clients/', include('project_name.app_name.urls'))
then in a template you can create a link for a certain client like this::
{% url "app_name.client" client.id %}
The URL will look like ``/clients/client/123/``.
The first argument can also be a named URL instead of the Python path to
the view callable. For example if the URLconf entry looks like this::
url('^client/(\d+)/$', name='client-detail-view')
then in the template you can use::
{% url "client-detail-view" client.id %}
There is even another possible value type for the first argument. It can be
the name of a template variable that will be evaluated to obtain the view
name or the URL name, e.g.::
{% with view_path="app_name.client" %}
{% url view_path client.id %}
{% endwith %}
or,
{% with url_name="client-detail-view" %}
{% url url_name client.id %}
{% endwith %}
"""
bits = token.split_contents()
if len(bits) < 2:
raise TemplateSyntaxError("'%s' takes at least one argument"
" (path to a view)" % bits[0])
viewname = parser.compile_filter(bits[1])
args = []
kwargs = {}
asvar = None
bits = bits[2:]
if len(bits) >= 2 and bits[-2] == 'as':
asvar = bits[-1]
bits = bits[:-2]
if len(bits):
for bit in bits:
match = kwarg_re.match(bit)
if not match:
raise TemplateSyntaxError("Malformed arguments to url tag")
name, value = match.groups()
if name:
kwargs[name] = parser.compile_filter(value)
else:
args.append(parser.compile_filter(value))
return URLNode(viewname, args, kwargs, asvar, legacy_view_name=False)
# Used for deprecation path during 1.3/1.4, will be removed in 2.0
return default_url(parser, token)

View File

@ -279,3 +279,6 @@ these changes.
goal of removing all ``django.contrib`` references from the core
Django codebase. The old shortcut will be removed in the 2.0
release.
* ``ssi`` and ``url`` template tags will be removed from the ``future`` template
tag library (used during the 1.3/1.4 deprecation period).

View File

@ -2034,7 +2034,6 @@ To allow easier reversing of the admin urls in templates, Django provides an
.. code-block:: html+django
{% load admin_urls %}
{% load url from future %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>

View File

@ -941,12 +941,15 @@ Like a simple :ttag:`include` tag, ``{% ssi %}`` includes the contents of
another file -- which must be specified using an absolute path -- in the
current page::
{% ssi /home/html/ljworld.com/includes/right_generic.html %}
{% ssi '/home/html/ljworld.com/includes/right_generic.html' %}
The first parameter of ``ssi`` can be a quoted literal or any other context
variable.
If the optional "parsed" parameter is given, the contents of the included
file are evaluated as template code, within the current context::
{% ssi /home/html/ljworld.com/includes/right_generic.html parsed %}
{% ssi '/home/html/ljworld.com/includes/right_generic.html' parsed %}
Note that if you use ``{% ssi %}``, you'll need to define
:setting:`ALLOWED_INCLUDE_ROOTS` in your Django settings, as a security
@ -954,30 +957,6 @@ measure.
See also: :ttag:`{% include %}<include>`.
.. admonition:: Forwards compatibility
.. versionchanged:: 1.3
In Django 1.5, the behavior of the :ttag:`ssi` template tag will
change, with the first argument being made into a context
variable, rather than being a special case unquoted constant. This
will allow the :ttag:`ssi` tag to use a context variable as the
value of the page to be included.
In order to provide a forwards compatibility path, Django 1.3
provides a future compatibility library -- ``future`` -- that
implements the new behavior. To use this library, add a
:ttag:`load` call at the top of any template using the :ttag:`ssi`
tag, and wrap the first argument to the :ttag:`ssi` tag in quotes.
For example::
{% load ssi from future %}
{% ssi '/home/html/ljworld.com/includes/right_generic.html' %}
In Django 1.5, the unquoted constant behavior will be replaced
with the behavior provided by the ``future`` tag library.
Existing templates should be migrated to use the new syntax.
.. templatetag:: templatetag
templatetag
@ -1013,15 +992,16 @@ given view function and optional parameters. This is a way to output links
without violating the DRY principle by having to hard-code URLs in your
templates::
{% url path.to.some_view v1 v2 %}
{% url 'path.to.some_view' v1 v2 %}
The first argument is a path to a view function in the format
``package.package.module.function``. Additional arguments are optional and
``package.package.module.function``. It can be a quoted literal or any other
context variable. Additional arguments are optional and
should be space-separated values that will be used as arguments in the URL.
The example above shows passing positional arguments. Alternatively you may
use keyword syntax::
{% url path.to.some_view arg1=v1 arg2=v2 %}
{% url 'path.to.some_view' arg1=v1 arg2=v2 %}
Do not mix both positional and keyword syntax in a single call. All arguments
required by the URLconf should be present.
@ -1043,7 +1023,7 @@ such as this:
...then, in a template, you can create a link to this view like this::
{% url app_views.client client.id %}
{% url 'app_views.client' client.id %}
The template tag will output the string ``/clients/client/123/``.
@ -1059,79 +1039,26 @@ If you'd like to retrieve a URL without displaying it, you can use a slightly
different call::
{% url path.to.view arg arg2 as the_url %}
{% 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::
{% url path.to.view as the_url %}
{% url 'path.to.view' as the_url %}
{% if the_url %}
<a href="{{ the_url }}">Link to optional stuff</a>
{% endif %}
If you'd like to retrieve a namespaced URL, specify the fully qualified name::
{% url myapp:view-name %}
{% url 'myapp:view-name' %}
This will follow the normal :ref:`namespaced URL resolution strategy
<topics-http-reversing-url-namespaces>`, including using any hints provided
by the context as to the current application.
.. versionchanged:: 1.2
For backwards compatibility, the ``{% url %}`` tag also supports the
use of commas to separate arguments. You shouldn't use this in any new
projects, but for the sake of the people who are still using it,
here's what it looks like::
{% url path.to.view arg,arg2 %}
{% url path.to.view arg, arg2 %}
This syntax doesn't support the use of literal commas, or equals
signs. Did we mention you shouldn't use this syntax in any new
projects?
.. admonition:: Forwards compatibility
.. versionchanged:: 1.3
In Django 1.5, the behavior of the :ttag:`url` template tag will
change, with the first argument being made into a context
variable, rather than being a special case unquoted constant. This
will allow the :ttag:`url` tag to use a context variable as the
value of the URL name to be reversed.
In order to provide a forwards compatibility path, Django 1.3
provides a future compatibility library -- ``future`` -- that
implements the new behavior. To use this library, add a
:ttag:`load` call at the top of any template using the :ttag:`url`
tag, and wrap the first argument to the :ttag:`url` tag in quotes.
For example::
{% load url from future %}
{% url 'app_views.client' %}
{% url 'myapp:view-name' %}
{% with view_path="app_views.client" %}
{% url view_path client.id %}
{% endwith %}
{% with url_name="client-detail-view" %}
{% url url_name client.id %}
{% endwith %}
The new library also drops support for the comma syntax for
separating arguments to the :ttag:`url` template tag.
In Django 1.5, the old behavior will be replaced with the behavior
provided by the ``future`` tag library. Existing templates be
migrated to use the new syntax.
.. templatetag:: widthratio
widthratio

View File

@ -1020,7 +1020,6 @@ The login_required decorator
.. code-block:: html+django
{% extends "base.html" %}
{% load url from future %}
{% block content %}
@ -1242,7 +1241,6 @@ includes a few other useful built-in views located in
.. code-block:: html+django
{% load url from future %}
Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol}}://{{ site_name }}{% url 'auth_password_reset_confirm' uidb36=uid token=token %}

View File

@ -208,7 +208,7 @@ Include a form in ``template.html`` that will ``POST`` to this view:
.. code-block:: html+django
{% load tz %}{% load url from future %}
{% load tz %}
<form action="{% url 'set_timezone' %}" method="POST">
{% csrf_token %}
<label for="timezone">Time zone:</label>

View File

@ -243,45 +243,30 @@ class URLTagTests(URLTestCaseBase):
"""
Test if the language tag works.
"""
def setUp(self):
self.save_warnings_state()
warnings.filterwarnings('ignore', category=DeprecationWarning,
module='django.template.defaulttags')
def tearDown(self):
self.restore_warnings_state()
def test_strings_only(self):
t = Template("""{% load i18n %}
{% language 'nl' %}{% url no-prefix-translated %}{% endlanguage %}
{% language 'pt-br' %}{% url no-prefix-translated %}{% endlanguage %}""")
{% language 'nl' %}{% url 'no-prefix-translated' %}{% endlanguage %}
{% language 'pt-br' %}{% url 'no-prefix-translated' %}{% endlanguage %}""")
self.assertEqual(t.render(Context({})).strip().split(),
[u'/vertaald/', u'/traduzidos/'])
def test_context(self):
ctx = Context({'lang1':'nl', 'lang2':'pt-br'})
tpl = Template("""{% load i18n %}
{% language lang1 %}{% url no-prefix-translated %}{% endlanguage %}
{% language lang2 %}{% url no-prefix-translated %}{% endlanguage %}""")
{% language lang1 %}{% url 'no-prefix-translated' %}{% endlanguage %}
{% language lang2 %}{% url 'no-prefix-translated' %}{% endlanguage %}""")
self.assertEqual(tpl.render(ctx).strip().split(),
[u'/vertaald/', u'/traduzidos/'])
def test_args(self):
tpl = Template("""{% load i18n %}
{% language 'nl' %}{% url no-prefix-translated-slug 'apo' %}{% endlanguage %}
{% language 'pt-br' %}{% url no-prefix-translated-slug 'apo' %}{% endlanguage %}""")
{% language 'nl' %}{% url 'no-prefix-translated-slug' 'apo' %}{% endlanguage %}
{% language 'pt-br' %}{% url 'no-prefix-translated-slug' 'apo' %}{% endlanguage %}""")
self.assertEqual(tpl.render(Context({})).strip().split(),
[u'/vertaald/apo/', u'/traduzidos/apo/'])
def test_kwargs(self):
tpl = Template("""{% load i18n %}
{% language 'nl' %}{% url no-prefix-translated-slug slug='apo' %}{% endlanguage %}
{% language 'pt-br' %}{% url no-prefix-translated-slug slug='apo' %}{% endlanguage %}""")
self.assertEqual(tpl.render(Context({})).strip().split(),
[u'/vertaald/apo/', u'/traduzidos/apo/'])
def test_future_kwargs(self):
tpl = Template("""{% load i18n %}{% load url from future %}
{% language 'nl' %}{% url 'no-prefix-translated-slug' slug='apo' %}{% endlanguage %}
{% language 'pt-br' %}{% url 'no-prefix-translated-slug' slug='apo' %}{% endlanguage %}""")
self.assertEqual(tpl.render(Context({})).strip().split(),

View File

@ -1,2 +1,2 @@
{% load url from future %}This is where you can find the snark: {% url "snark" %}
{% now "U.u" %}
This is where you can find the snark: {% url "snark" %}
{% now "U.u" %}

View File

@ -1412,34 +1412,21 @@ class Templates(unittest.TestCase):
### SSI TAG ########################################################
# Test normal behavior
'old-ssi01': ('{%% ssi %s %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'),
'old-ssi02': ('{%% ssi %s %%}' % os.path.join(basedir, 'not_here'), {}, ''),
# Test parsed output
'old-ssi06': ('{%% ssi %s parsed %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'),
'old-ssi07': ('{%% ssi %s parsed %%}' % os.path.join(basedir, 'not_here'), {'test': 'Look ma! It parsed!'}, ''),
# Test space in file name
'old-ssi08': ('{%% ssi %s %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {}, template.TemplateSyntaxError),
'old-ssi09': ('{%% ssi %s parsed %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {'test': 'Look ma! It parsed!'}, template.TemplateSyntaxError),
# Future compatibility
# Test normal behavior
'ssi01': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'),
'ssi02': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(basedir, 'not_here'), {}, ''),
'ssi03': ("{%% load ssi from future %%}{%% ssi '%s' %%}" % os.path.join(basedir, 'not_here'), {}, ''),
'ssi01': ('{%% ssi "%s" %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'),
'ssi02': ('{%% ssi "%s" %%}' % os.path.join(basedir, 'not_here'), {}, ''),
'ssi03': ("{%% ssi '%s' %%}" % os.path.join(basedir, 'not_here'), {}, ''),
# Test passing as a variable
'ssi04': ('{% load ssi from future %}{% ssi ssi_file %}', {'ssi_file': os.path.join(basedir, 'templates', 'ssi_include.html')}, 'This is for testing an ssi include. {{ test }}\n'),
'ssi05': ('{% load ssi from future %}{% ssi ssi_file %}', {'ssi_file': 'no_file'}, ''),
# Test parsed output
'ssi06': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'),
'ssi07': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(basedir, 'not_here'), {'test': 'Look ma! It parsed!'}, ''),
'ssi06': ('{%% ssi "%s" parsed %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'),
'ssi07': ('{%% ssi "%s" parsed %%}' % os.path.join(basedir, 'not_here'), {'test': 'Look ma! It parsed!'}, ''),
# Test space in file name
'ssi08': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {}, 'This is for testing an ssi include with spaces in its name. {{ test }}\n'),
'ssi09': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include with spaces in its name. Look ma! It parsed!\n'),
'ssi08': ('{%% ssi "%s" %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {}, 'This is for testing an ssi include with spaces in its name. {{ test }}\n'),
'ssi09': ('{%% ssi "%s" parsed %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include with spaces in its name. Look ma! It parsed!\n'),
### TEMPLATETAG TAG #######################################################
'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
@ -1510,103 +1497,54 @@ class Templates(unittest.TestCase):
### URL TAG ########################################################
# Successes
'legacyurl02': ('{% url regressiontests.templates.views.client_action id=client.id,action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'legacyurl02a': ('{% url regressiontests.templates.views.client_action client.id,"update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'legacyurl02b': ("{% url regressiontests.templates.views.client_action id=client.id,action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'legacyurl02c': ("{% url regressiontests.templates.views.client_action client.id,'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'legacyurl10': ('{% url regressiontests.templates.views.client_action id=client.id,action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
'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/'),
'legacyurl14': ('{% url regressiontests.templates.views.client_action client.id, arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
'legacyurl16': ('{% url regressiontests.templates.views.client_action action="update",id="1" %}', {}, '/url_tag/client/1/update/'),
'legacyurl16a': ("{% url regressiontests.templates.views.client_action action='update',id='1' %}", {}, '/url_tag/client/1/update/'),
'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/'),
'url01': ('{% url "regressiontests.templates.views.client" client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
'url02': ('{% url "regressiontests.templates.views.client_action" id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'url02a': ('{% url "regressiontests.templates.views.client_action" client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'url02b': ("{% url 'regressiontests.templates.views.client_action' id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'url02c': ("{% url 'regressiontests.templates.views.client_action' client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'url03': ('{% url "regressiontests.templates.views.index" %}', {}, '/url_tag/'),
'url04': ('{% url "named.client" client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
'url05': (u'{% url "метка_оператора" v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url06': (u'{% url "метка_оператора_2" tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'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/'),
'url08': (u'{% url "метка_оператора" v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url09': (u'{% url "метка_оператора_2" tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url10': ('{% url "regressiontests.templates.views.client_action" id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
'url11': ('{% url "regressiontests.templates.views.client_action" id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),
'url12': ('{% url "regressiontests.templates.views.client_action" id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),
'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/'),
'url14': ('{% url "regressiontests.templates.views.client_action" client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
'url15': ('{% url "regressiontests.templates.views.client_action" 12 "test" %}', {}, '/url_tag/client/12/test/'),
'url18': ('{% url "regressiontests.templates.views.client" "1,2" %}', {}, '/url_tag/client/1,2/'),
'old-url01': ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
'old-url02': ('{% url regressiontests.templates.views.client_action id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'old-url02a': ('{% url regressiontests.templates.views.client_action client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'old-url02b': ("{% url regressiontests.templates.views.client_action id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'old-url02c': ("{% url regressiontests.templates.views.client_action client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'old-url03': ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),
'old-url04': ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
'old-url05': (u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'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/'),
'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/'),
'old-url08': (u'{% url метка_оператора v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'old-url09': (u'{% url метка_оператора_2 tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'old-url10': ('{% url regressiontests.templates.views.client_action id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
'old-url11': ('{% url regressiontests.templates.views.client_action id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),
'old-url12': ('{% url regressiontests.templates.views.client_action id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),
'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/'),
'old-url14': ('{% url regressiontests.templates.views.client_action client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
'old-url15': ('{% url regressiontests.templates.views.client_action 12 "test" %}', {}, '/url_tag/client/12/test/'),
'old-url16': ('{% url regressiontests.templates.views.client "1,2" %}', {}, '/url_tag/client/1,2/'),
'url19': ('{% url named_url client.id %}', {'named_url': 'regressiontests.templates.views.client', 'client': {'id': 1}}, '/url_tag/client/1/'),
'url20': ('{% url url_name_in_var client.id %}', {'url_name_in_var': 'named.client', 'client': {'id': 1}}, '/url_tag/named-client/1/'),
# Failures
'old-url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
'old-url-fail02': ('{% url no_such_view %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'old-url-fail03': ('{% url regressiontests.templates.views.client %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'old-url-fail04': ('{% url view id, %}', {}, template.TemplateSyntaxError),
'old-url-fail05': ('{% url view id= %}', {}, template.TemplateSyntaxError),
'old-url-fail06': ('{% url view a.id=id %}', {}, template.TemplateSyntaxError),
'old-url-fail07': ('{% url view a.id!id %}', {}, template.TemplateSyntaxError),
'old-url-fail08': ('{% url view id="unterminatedstring %}', {}, template.TemplateSyntaxError),
'old-url-fail09': ('{% url view id=", %}', {}, template.TemplateSyntaxError),
'url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
'url-fail02': ('{% url "no_such_view" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail03': ('{% url "regressiontests.templates.views.client" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail04': ('{% url "view" id, %}', {}, template.TemplateSyntaxError),
'url-fail05': ('{% url "view" id= %}', {}, template.TemplateSyntaxError),
'url-fail06': ('{% url "view" a.id=id %}', {}, template.TemplateSyntaxError),
'url-fail07': ('{% url "view" a.id!id %}', {}, template.TemplateSyntaxError),
'url-fail08': ('{% url "view" id="unterminatedstring %}', {}, template.TemplateSyntaxError),
'url-fail09': ('{% url "view" id=", %}', {}, template.TemplateSyntaxError),
'url-fail11': ('{% url named_url %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail12': ('{% url named_url %}', {'named_url': 'no_such_view'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail13': ('{% url named_url %}', {'named_url': 'regressiontests.templates.views.client'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail14': ('{% url named_url id, %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail15': ('{% url named_url id= %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail16': ('{% url named_url a.id=id %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail17': ('{% url named_url a.id!id %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail18': ('{% url named_url id="unterminatedstring %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail19': ('{% url named_url id=", %}', {'named_url': 'view'}, template.TemplateSyntaxError),
# {% url ... as var %}
'old-url-asvar01': ('{% url regressiontests.templates.views.index as url %}', {}, ''),
'old-url-asvar02': ('{% url regressiontests.templates.views.index as url %}{{ url }}', {}, '/url_tag/'),
'old-url-asvar03': ('{% url no_such_view as url %}{{ url }}', {}, ''),
# forward compatibility
# Successes
'url01': ('{% load url from future %}{% url "regressiontests.templates.views.client" client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
'url02': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'url02a': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'url02b': ("{% load url from future %}{% url 'regressiontests.templates.views.client_action' id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'url02c': ("{% load url from future %}{% url 'regressiontests.templates.views.client_action' client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'url03': ('{% load url from future %}{% url "regressiontests.templates.views.index" %}', {}, '/url_tag/'),
'url04': ('{% load url from future %}{% url "named.client" client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
'url05': (u'{% load url from future %}{% url "метка_оператора" v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url06': (u'{% load url from future %}{% url "метка_оператора_2" tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url07': (u'{% load url from future %}{% 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/'),
'url08': (u'{% load url from future %}{% url "метка_оператора" v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url09': (u'{% load url from future %}{% url "метка_оператора_2" tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url10': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
'url11': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),
'url12': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),
'url13': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
'url14': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
'url15': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" 12 "test" %}', {}, '/url_tag/client/12/test/'),
'url18': ('{% load url from future %}{% url "regressiontests.templates.views.client" "1,2" %}', {}, '/url_tag/client/1,2/'),
'url19': ('{% load url from future %}{% url named_url client.id %}', {'named_url': 'regressiontests.templates.views.client', 'client': {'id': 1}}, '/url_tag/client/1/'),
'url20': ('{% load url from future %}{% url url_name_in_var client.id %}', {'url_name_in_var': 'named.client', 'client': {'id': 1}}, '/url_tag/named-client/1/'),
# Failures
'url-fail01': ('{% load url from future %}{% url %}', {}, template.TemplateSyntaxError),
'url-fail02': ('{% load url from future %}{% url "no_such_view" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail03': ('{% load url from future %}{% url "regressiontests.templates.views.client" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail04': ('{% load url from future %}{% url "view" id, %}', {}, template.TemplateSyntaxError),
'url-fail05': ('{% load url from future %}{% url "view" id= %}', {}, template.TemplateSyntaxError),
'url-fail06': ('{% load url from future %}{% url "view" a.id=id %}', {}, template.TemplateSyntaxError),
'url-fail07': ('{% load url from future %}{% url "view" a.id!id %}', {}, template.TemplateSyntaxError),
'url-fail08': ('{% load url from future %}{% url "view" id="unterminatedstring %}', {}, template.TemplateSyntaxError),
'url-fail09': ('{% load url from future %}{% url "view" id=", %}', {}, template.TemplateSyntaxError),
'url-fail11': ('{% load url from future %}{% url named_url %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail12': ('{% load url from future %}{% url named_url %}', {'named_url': 'no_such_view'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail13': ('{% load url from future %}{% url named_url %}', {'named_url': 'regressiontests.templates.views.client'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch)),
'url-fail14': ('{% load url from future %}{% url named_url id, %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail15': ('{% load url from future %}{% url named_url id= %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail16': ('{% load url from future %}{% url named_url a.id=id %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail17': ('{% load url from future %}{% url named_url a.id!id %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail18': ('{% load url from future %}{% url named_url id="unterminatedstring %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail19': ('{% load url from future %}{% url named_url id=", %}', {'named_url': 'view'}, template.TemplateSyntaxError),
# {% url ... as var %}
'url-asvar01': ('{% load url from future %}{% url "regressiontests.templates.views.index" as url %}', {}, ''),
'url-asvar02': ('{% load url from future %}{% url "regressiontests.templates.views.index" as url %}{{ url }}', {}, '/url_tag/'),
'url-asvar03': ('{% load url from future %}{% url "no_such_view" as url %}{{ url }}', {}, ''),
'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 ######################################################
'cache03': ('{% load cache %}{% cache 2 test %}cache03{% endcache %}', {}, 'cache03'),

View File

@ -3,11 +3,10 @@ from django.template import Template, Context
from django.http import HttpResponse
def inner_view(request):
content = Template('{% load url from future %}'
'{% url "outer" as outer_url %}outer:{{ outer_url }},'
content = Template('{% url "outer" as outer_url %}outer:{{ outer_url }},'
'{% url "inner" as inner_url %}inner:{{ inner_url }}').render(Context())
return HttpResponse(content)
urlpatterns = patterns('',
url(r'^second_test/$', inner_view, name='inner'),
)
)