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" %} {% extends "admin/base_site.html" %}
{% load i18n %} {% load i18n %}
{% load url from future %}
{% block breadcrumbs %} {% block breadcrumbs %}
<div class="breadcrumbs"> <div class="breadcrumbs">

View File

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

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_site.html" %}
{% load i18n admin_static admin_modify %} {% load i18n admin_static admin_modify %}
{% load url from future %}
{% load admin_urls %} {% load admin_urls %}
{% block extrahead %}{{ block.super }} {% 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 %}> <html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head> <head>
<title>{% block title %}{% endblock %}</title> <title>{% block title %}{% endblock %}</title>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_site.html" %}
{% load i18n admin_static %} {% 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 %} {% 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" %} {% extends "admin/base_site.html" %}
{% load i18n %} {% load i18n %}
{% load url from future %}
{% load admin_urls %} {% load admin_urls %}
{% block breadcrumbs %} {% block breadcrumbs %}

View File

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

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_site.html" %}
{% load i18n static %} {% 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 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 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 %} {% block breadcrumbs %}

View File

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

View File

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

View File

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_site.html" %}
{% load i18n %} {% load i18n %}
{% load url from future %}
{% block breadcrumbs %} {% block breadcrumbs %}
<div class="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 %} {% 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:" %} {% trans "Please go to the following page and choose a new password:" %}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -315,15 +315,12 @@ def include_is_allowed(filepath):
return False return False
class SsiNode(Node): class SsiNode(Node):
def __init__(self, filepath, parsed, legacy_filepath=True): def __init__(self, filepath, parsed):
self.filepath = filepath self.filepath = filepath
self.parsed = parsed self.parsed = parsed
self.legacy_filepath = legacy_filepath
def render(self, context): def render(self, context):
filepath = self.filepath filepath = self.filepath.resolve(context)
if not self.legacy_filepath:
filepath = filepath.resolve(context)
if not include_is_allowed(filepath): if not include_is_allowed(filepath):
if settings.DEBUG: if settings.DEBUG:
@ -385,9 +382,8 @@ class TemplateTagNode(Node):
return self.mapping.get(self.tagtype, '') return self.mapping.get(self.tagtype, '')
class URLNode(Node): 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.view_name = view_name
self.legacy_view_name = legacy_view_name
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
self.asvar = asvar self.asvar = asvar
@ -398,9 +394,7 @@ class URLNode(Node):
kwargs = dict([(smart_str(k, 'ascii'), v.resolve(context)) kwargs = dict([(smart_str(k, 'ascii'), v.resolve(context))
for k, v in self.kwargs.items()]) for k, v in self.kwargs.items()])
view_name = self.view_name view_name = self.view_name.resolve(context)
if not self.legacy_view_name:
view_name = view_name.resolve(context)
# Try to look up the URL twice: once given the view name, and again # 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, # 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 -- of another file -- which must be specified using an absolute path --
in the current page:: 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 If the optional "parsed" parameter is given, the contents of the included
file are evaluated as template code, with the current context:: 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 %}
""" """
bits = token.split_contents()
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()
parsed = False parsed = False
if len(bits) not in (2, 3): if len(bits) not in (2, 3):
raise TemplateSyntaxError("'ssi' tag takes one argument: the path to" raise TemplateSyntaxError("'ssi' tag takes one argument: the path to"
@ -992,7 +981,8 @@ def ssi(parser, token):
else: else:
raise TemplateSyntaxError("Second (optional) argument to %s tag" raise TemplateSyntaxError("Second (optional) argument to %s tag"
" must be 'parsed'" % bits[0]) " 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 @register.tag
def load(parser, token): 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 This is a way to define links that aren't tied to a particular URL
configuration:: configuration::
{% url path.to.some_view arg1 arg2 %} {% url "path.to.some_view" arg1 arg2 %}
or 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 or just ``app_name.view_name`` without the project name if the view is
located inside the project. Other arguments are comma-separated values located inside the project.
that will be filled in place of positional and keyword arguments in the
URL. All arguments for the URL should be present. 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 For example if you have a view ``app_name.client`` taking client's id and
the corresponding line in a URLconf looks like this:: 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:: 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 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() bits = token.split_contents()
if len(bits) < 2: if len(bits) < 2:
raise TemplateSyntaxError("'%s' takes at least one argument" raise TemplateSyntaxError("'%s' takes at least one argument"
" (path to a view)" % bits[0]) " (path to a view)" % bits[0])
viewname = bits[1] viewname = parser.compile_filter(bits[1])
args = [] args = []
kwargs = {} kwargs = {}
asvar = None asvar = None
@ -1247,38 +1260,6 @@ def url(parser, token):
asvar = bits[-1] asvar = bits[-1]
bits = bits[:-2] 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): if len(bits):
for bit in bits: for bit in bits:
match = kwarg_re.match(bit) match = kwarg_re.match(bit)
@ -1290,7 +1271,7 @@ def url(parser, token):
else: else:
args.append(parser.compile_filter(value)) args.append(parser.compile_filter(value))
return URLNode(viewname, args, kwargs, asvar, legacy_view_name=True) return URLNode(viewname, args, kwargs, asvar)
@register.tag @register.tag
def widthratio(parser, token): def widthratio(parser, token):

View File

@ -1,124 +1,14 @@
from django.template import Library, TemplateSyntaxError from django.template import Library
from django.template.defaulttags import kwarg_re, SsiNode, URLNode from django.template.defaulttags import url as default_url, ssi as default_ssi
register = Library() register = Library()
@register.tag @register.tag
def ssi(parser, token): def ssi(parser, token):
""" # Used for deprecation path during 1.3/1.4, will be removed in 2.0
Outputs the contents of a given file into the page. return default_ssi(parser, token)
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)
@register.tag @register.tag
def url(parser, token): def url(parser, token):
""" # Used for deprecation path during 1.3/1.4, will be removed in 2.0
Returns an absolute URL matching given view with its parameters. return default_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 %}
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)

View File

@ -279,3 +279,6 @@ these changes.
goal of removing all ``django.contrib`` references from the core goal of removing all ``django.contrib`` references from the core
Django codebase. The old shortcut will be removed in the 2.0 Django codebase. The old shortcut will be removed in the 2.0
release. 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 .. code-block:: html+django
{% load admin_urls %} {% load admin_urls %}
{% load url from future %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a> <a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this 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 another file -- which must be specified using an absolute path -- in the
current page:: 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 If the optional "parsed" parameter is given, the contents of the included
file are evaluated as template code, within the current context:: 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 Note that if you use ``{% ssi %}``, you'll need to define
:setting:`ALLOWED_INCLUDE_ROOTS` in your Django settings, as a security :setting:`ALLOWED_INCLUDE_ROOTS` in your Django settings, as a security
@ -954,30 +957,6 @@ measure.
See also: :ttag:`{% include %}<include>`. 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:: 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 without violating the DRY principle by having to hard-code URLs in your
templates:: 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 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. should be space-separated values that will be used as arguments in the URL.
The example above shows passing positional arguments. Alternatively you may The example above shows passing positional arguments. Alternatively you may
use keyword syntax:: 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 Do not mix both positional and keyword syntax in a single call. All arguments
required by the URLconf should be present. 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:: ...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/``. 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:: 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> <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 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:: 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 %} {% if the_url %}
<a href="{{ the_url }}">Link to optional stuff</a> <a href="{{ the_url }}">Link to optional stuff</a>
{% endif %} {% endif %}
If you'd like to retrieve a namespaced URL, specify the fully qualified name:: 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 This will follow the normal :ref:`namespaced URL resolution strategy
<topics-http-reversing-url-namespaces>`, including using any hints provided <topics-http-reversing-url-namespaces>`, including using any hints provided
by the context as to the current application. 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 .. templatetag:: widthratio
widthratio widthratio

View File

@ -1020,7 +1020,6 @@ The login_required decorator
.. code-block:: html+django .. code-block:: html+django
{% extends "base.html" %} {% extends "base.html" %}
{% load url from future %}
{% block content %} {% block content %}
@ -1242,7 +1241,6 @@ includes a few other useful built-in views located in
.. code-block:: html+django .. code-block:: html+django
{% load url from future %}
Someone asked for password reset for email {{ email }}. Follow the link below: Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol}}://{{ site_name }}{% url 'auth_password_reset_confirm' uidb36=uid token=token %} {{ 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 .. code-block:: html+django
{% load tz %}{% load url from future %} {% load tz %}
<form action="{% url 'set_timezone' %}" method="POST"> <form action="{% url 'set_timezone' %}" method="POST">
{% csrf_token %} {% csrf_token %}
<label for="timezone">Time zone:</label> <label for="timezone">Time zone:</label>

View File

@ -243,45 +243,30 @@ class URLTagTests(URLTestCaseBase):
""" """
Test if the language tag works. 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): def test_strings_only(self):
t = Template("""{% load i18n %} t = Template("""{% load i18n %}
{% language 'nl' %}{% url no-prefix-translated %}{% endlanguage %} {% language 'nl' %}{% url 'no-prefix-translated' %}{% endlanguage %}
{% language 'pt-br' %}{% url no-prefix-translated %}{% endlanguage %}""") {% language 'pt-br' %}{% url 'no-prefix-translated' %}{% endlanguage %}""")
self.assertEqual(t.render(Context({})).strip().split(), self.assertEqual(t.render(Context({})).strip().split(),
[u'/vertaald/', u'/traduzidos/']) [u'/vertaald/', u'/traduzidos/'])
def test_context(self): def test_context(self):
ctx = Context({'lang1':'nl', 'lang2':'pt-br'}) ctx = Context({'lang1':'nl', 'lang2':'pt-br'})
tpl = Template("""{% load i18n %} tpl = Template("""{% load i18n %}
{% language lang1 %}{% url no-prefix-translated %}{% endlanguage %} {% language lang1 %}{% url 'no-prefix-translated' %}{% endlanguage %}
{% language lang2 %}{% url no-prefix-translated %}{% endlanguage %}""") {% language lang2 %}{% url 'no-prefix-translated' %}{% endlanguage %}""")
self.assertEqual(tpl.render(ctx).strip().split(), self.assertEqual(tpl.render(ctx).strip().split(),
[u'/vertaald/', u'/traduzidos/']) [u'/vertaald/', u'/traduzidos/'])
def test_args(self): def test_args(self):
tpl = Template("""{% load i18n %} tpl = Template("""{% load i18n %}
{% language 'nl' %}{% 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 %}""") {% language 'pt-br' %}{% url 'no-prefix-translated-slug' 'apo' %}{% endlanguage %}""")
self.assertEqual(tpl.render(Context({})).strip().split(), self.assertEqual(tpl.render(Context({})).strip().split(),
[u'/vertaald/apo/', u'/traduzidos/apo/']) [u'/vertaald/apo/', u'/traduzidos/apo/'])
def test_kwargs(self): def test_kwargs(self):
tpl = Template("""{% load i18n %} 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 'nl' %}{% url 'no-prefix-translated-slug' slug='apo' %}{% endlanguage %}
{% language 'pt-br' %}{% 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(), 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" %} This is where you can find the snark: {% url "snark" %}
{% now "U.u" %} {% now "U.u" %}

View File

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

View File

@ -3,8 +3,7 @@ from django.template import Template, Context
from django.http import HttpResponse from django.http import HttpResponse
def inner_view(request): def inner_view(request):
content = Template('{% load url from future %}' content = Template('{% url "outer" as outer_url %}outer:{{ outer_url }},'
'{% url "outer" as outer_url %}outer:{{ outer_url }},'
'{% url "inner" as inner_url %}inner:{{ inner_url }}').render(Context()) '{% url "inner" as inner_url %}inner:{{ inner_url }}').render(Context())
return HttpResponse(content) return HttpResponse(content)