Fixed #18651 -- Enabled optional assignments for simple_tag().
This commit is contained in:
parent
8adc59038c
commit
cd4282816d
|
@ -61,7 +61,8 @@ from django.apps import apps
|
||||||
from django.template.context import (BaseContext, Context, RequestContext, # NOQA: imported for backwards compatibility
|
from django.template.context import (BaseContext, Context, RequestContext, # NOQA: imported for backwards compatibility
|
||||||
ContextPopException)
|
ContextPopException)
|
||||||
from django.utils import lru_cache
|
from django.utils import lru_cache
|
||||||
from django.utils.deprecation import RemovedInDjango20Warning
|
from django.utils.deprecation import (RemovedInDjango20Warning,
|
||||||
|
RemovedInDjango21Warning)
|
||||||
from django.utils.itercompat import is_iterable
|
from django.utils.itercompat import is_iterable
|
||||||
from django.utils.text import (smart_split, unescape_string_literal,
|
from django.utils.text import (smart_split, unescape_string_literal,
|
||||||
get_text_list)
|
get_text_list)
|
||||||
|
@ -1021,9 +1022,9 @@ def token_kwargs(bits, parser, support_legacy=False):
|
||||||
def parse_bits(parser, bits, params, varargs, varkw, defaults,
|
def parse_bits(parser, bits, params, varargs, varkw, defaults,
|
||||||
takes_context, name):
|
takes_context, name):
|
||||||
"""
|
"""
|
||||||
Parses bits for template tag helpers (simple_tag, include_tag and
|
Parses bits for template tag helpers simple_tag and inclusion_tag, in
|
||||||
assignment_tag), in particular by detecting syntax errors and by
|
particular by detecting syntax errors and by extracting positional and
|
||||||
extracting positional and keyword arguments.
|
keyword arguments.
|
||||||
"""
|
"""
|
||||||
if takes_context:
|
if takes_context:
|
||||||
if params[0] == 'context':
|
if params[0] == 'context':
|
||||||
|
@ -1099,9 +1100,9 @@ def generic_tag_compiler(parser, token, params, varargs, varkw, defaults,
|
||||||
|
|
||||||
class TagHelperNode(Node):
|
class TagHelperNode(Node):
|
||||||
"""
|
"""
|
||||||
Base class for tag helper nodes such as SimpleNode, InclusionNode and
|
Base class for tag helper nodes such as SimpleNode and InclusionNode.
|
||||||
AssignmentNode. Manages the positional and keyword arguments to be passed
|
Manages the positional and keyword arguments to be passed to the decorated
|
||||||
to the decorated function.
|
function.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, takes_context, args, kwargs):
|
def __init__(self, takes_context, args, kwargs):
|
||||||
|
@ -1191,17 +1192,31 @@ class Library(object):
|
||||||
params, varargs, varkw, defaults = getargspec(func)
|
params, varargs, varkw, defaults = getargspec(func)
|
||||||
|
|
||||||
class SimpleNode(TagHelperNode):
|
class SimpleNode(TagHelperNode):
|
||||||
|
def __init__(self, takes_context, args, kwargs, target_var):
|
||||||
|
super(SimpleNode, self).__init__(takes_context, args, kwargs)
|
||||||
|
self.target_var = target_var
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
|
resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
|
||||||
return func(*resolved_args, **resolved_kwargs)
|
output = func(*resolved_args, **resolved_kwargs)
|
||||||
|
if self.target_var is not None:
|
||||||
|
context[self.target_var] = output
|
||||||
|
return ''
|
||||||
|
return output
|
||||||
|
|
||||||
function_name = (name or
|
function_name = (name or
|
||||||
getattr(func, '_decorated_function', func).__name__)
|
getattr(func, '_decorated_function', func).__name__)
|
||||||
compile_func = partial(generic_tag_compiler,
|
|
||||||
params=params, varargs=varargs, varkw=varkw,
|
def compile_func(parser, token):
|
||||||
defaults=defaults, name=function_name,
|
bits = token.split_contents()[1:]
|
||||||
takes_context=takes_context, node_class=SimpleNode)
|
target_var = None
|
||||||
|
if len(bits) >= 2 and bits[-2] == 'as':
|
||||||
|
target_var = bits[-1]
|
||||||
|
bits = bits[:-2]
|
||||||
|
args, kwargs = parse_bits(parser, bits, params,
|
||||||
|
varargs, varkw, defaults, takes_context, function_name)
|
||||||
|
return SimpleNode(takes_context, args, kwargs, target_var)
|
||||||
|
|
||||||
compile_func.__doc__ = func.__doc__
|
compile_func.__doc__ = func.__doc__
|
||||||
self.tag(function_name, compile_func)
|
self.tag(function_name, compile_func)
|
||||||
return func
|
return func
|
||||||
|
@ -1216,46 +1231,12 @@ class Library(object):
|
||||||
raise TemplateSyntaxError("Invalid arguments provided to simple_tag")
|
raise TemplateSyntaxError("Invalid arguments provided to simple_tag")
|
||||||
|
|
||||||
def assignment_tag(self, func=None, takes_context=None, name=None):
|
def assignment_tag(self, func=None, takes_context=None, name=None):
|
||||||
def dec(func):
|
warnings.warn(
|
||||||
params, varargs, varkw, defaults = getargspec(func)
|
"assignment_tag() is deprecated. Use simple_tag() instead",
|
||||||
|
RemovedInDjango21Warning,
|
||||||
class AssignmentNode(TagHelperNode):
|
stacklevel=2,
|
||||||
def __init__(self, takes_context, args, kwargs, target_var):
|
)
|
||||||
super(AssignmentNode, self).__init__(takes_context, args, kwargs)
|
return self.simple_tag(func, takes_context, name)
|
||||||
self.target_var = target_var
|
|
||||||
|
|
||||||
def render(self, context):
|
|
||||||
resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
|
|
||||||
context[self.target_var] = func(*resolved_args, **resolved_kwargs)
|
|
||||||
return ''
|
|
||||||
|
|
||||||
function_name = (name or
|
|
||||||
getattr(func, '_decorated_function', func).__name__)
|
|
||||||
|
|
||||||
def compile_func(parser, token):
|
|
||||||
bits = token.split_contents()[1:]
|
|
||||||
if len(bits) < 2 or bits[-2] != 'as':
|
|
||||||
raise TemplateSyntaxError(
|
|
||||||
"'%s' tag takes at least 2 arguments and the "
|
|
||||||
"second last argument must be 'as'" % function_name)
|
|
||||||
target_var = bits[-1]
|
|
||||||
bits = bits[:-2]
|
|
||||||
args, kwargs = parse_bits(parser, bits, params,
|
|
||||||
varargs, varkw, defaults, takes_context, function_name)
|
|
||||||
return AssignmentNode(takes_context, args, kwargs, target_var)
|
|
||||||
|
|
||||||
compile_func.__doc__ = func.__doc__
|
|
||||||
self.tag(function_name, compile_func)
|
|
||||||
return func
|
|
||||||
|
|
||||||
if func is None:
|
|
||||||
# @register.assignment_tag(...)
|
|
||||||
return dec
|
|
||||||
elif callable(func):
|
|
||||||
# @register.assignment_tag
|
|
||||||
return dec(func)
|
|
||||||
else:
|
|
||||||
raise TemplateSyntaxError("Invalid arguments provided to assignment_tag")
|
|
||||||
|
|
||||||
def inclusion_tag(self, file_name, takes_context=False, name=None):
|
def inclusion_tag(self, file_name, takes_context=False, name=None):
|
||||||
def dec(func):
|
def dec(func):
|
||||||
|
|
|
@ -388,7 +388,7 @@ Simple tags
|
||||||
.. method:: django.template.Library.simple_tag()
|
.. method:: django.template.Library.simple_tag()
|
||||||
|
|
||||||
Many template tags take a number of arguments -- strings or template variables
|
Many template tags take a number of arguments -- strings or template variables
|
||||||
-- and return a string after doing some processing based solely on
|
-- and return a result after doing some processing based solely on
|
||||||
the input arguments and some external information. For example, a
|
the input arguments and some external information. For example, a
|
||||||
``current_time`` tag might accept a format string and return the time as a
|
``current_time`` tag might accept a format string and return the time as a
|
||||||
string formatted accordingly.
|
string formatted accordingly.
|
||||||
|
@ -459,6 +459,18 @@ positional arguments. For example:
|
||||||
|
|
||||||
{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}
|
{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}
|
||||||
|
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
It's possible to store the tag results in a template variable rather than
|
||||||
|
directly outputting it. This is done by using the ``as`` argument followed by
|
||||||
|
the variable name. Doing so enables you to output the content yourself where
|
||||||
|
you see fit:
|
||||||
|
|
||||||
|
.. code-block:: html+django
|
||||||
|
|
||||||
|
{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
|
||||||
|
<p>The time is {{ the_time }}.</p>
|
||||||
|
|
||||||
.. _howto-custom-template-tags-inclusion-tags:
|
.. _howto-custom-template-tags-inclusion-tags:
|
||||||
|
|
||||||
Inclusion tags
|
Inclusion tags
|
||||||
|
@ -602,11 +614,15 @@ Assignment tags
|
||||||
|
|
||||||
.. method:: django.template.Library.assignment_tag()
|
.. method:: django.template.Library.assignment_tag()
|
||||||
|
|
||||||
|
.. deprecated:: 1.9
|
||||||
|
|
||||||
|
``simple_tag`` can now store results in a template variable and should
|
||||||
|
be used instead.
|
||||||
|
|
||||||
To ease the creation of tags setting a variable in the context, Django provides
|
To ease the creation of tags setting a variable in the context, Django provides
|
||||||
a helper function, ``assignment_tag``. This function works the same way as
|
a helper function, ``assignment_tag``. This function works the same way as
|
||||||
:ref:`simple_tag<howto-custom-template-tags-simple-tags>`, except that it
|
:meth:`~django.template.Library.simple_tag` except that it stores the tag's
|
||||||
stores the tag's result in a specified context variable instead of directly
|
result in a specified context variable instead of directly outputting it.
|
||||||
outputting it.
|
|
||||||
|
|
||||||
Our earlier ``current_time`` function could thus be written like this::
|
Our earlier ``current_time`` function could thus be written like this::
|
||||||
|
|
||||||
|
@ -622,38 +638,6 @@ followed by the variable name, and output it yourself where you see fit:
|
||||||
{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
|
{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
|
||||||
<p>The time is {{ the_time }}.</p>
|
<p>The time is {{ the_time }}.</p>
|
||||||
|
|
||||||
If your template tag needs to access the current context, you can use the
|
|
||||||
``takes_context`` argument when registering your tag::
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
|
||||||
def get_current_time(context, format_string):
|
|
||||||
timezone = context['timezone']
|
|
||||||
return your_get_current_time_method(timezone, format_string)
|
|
||||||
|
|
||||||
Note that the first parameter to the function *must* be called ``context``.
|
|
||||||
|
|
||||||
For more information on how the ``takes_context`` option works, see the section
|
|
||||||
on :ref:`inclusion tags<howto-custom-template-tags-inclusion-tags>`.
|
|
||||||
|
|
||||||
``assignment_tag`` functions may accept any number of positional or keyword
|
|
||||||
arguments. For example::
|
|
||||||
|
|
||||||
@register.assignment_tag
|
|
||||||
def my_tag(a, b, *args, **kwargs):
|
|
||||||
warning = kwargs['warning']
|
|
||||||
profile = kwargs['profile']
|
|
||||||
...
|
|
||||||
return ...
|
|
||||||
|
|
||||||
Then in the template any number of arguments, separated by spaces, may be
|
|
||||||
passed to the template tag. Like in Python, the values for keyword arguments
|
|
||||||
are set using the equal sign ("``=``") and must be provided after the
|
|
||||||
positional arguments. For example:
|
|
||||||
|
|
||||||
.. code-block:: html+django
|
|
||||||
|
|
||||||
{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile as the_result %}
|
|
||||||
|
|
||||||
Advanced custom template tags
|
Advanced custom template tags
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ details on these changes.
|
||||||
|
|
||||||
* The ``django.forms.extras`` package will be removed.
|
* The ``django.forms.extras`` package will be removed.
|
||||||
|
|
||||||
|
* The ``assignment_tag`` helper will be removed.
|
||||||
|
|
||||||
.. _deprecation-removed-in-2.0:
|
.. _deprecation-removed-in-2.0:
|
||||||
|
|
||||||
2.0
|
2.0
|
||||||
|
|
|
@ -137,7 +137,9 @@ Signals
|
||||||
Templates
|
Templates
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
* ...
|
* Template tags created with the :meth:`~django.template.Library.simple_tag`
|
||||||
|
helper can now store results in a template variable by using the ``as``
|
||||||
|
argument.
|
||||||
|
|
||||||
Requests and Responses
|
Requests and Responses
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -194,6 +196,15 @@ Miscellaneous
|
||||||
Features deprecated in 1.9
|
Features deprecated in 1.9
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
``assignment_tag()``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Django 1.4 added the ``assignment_tag`` helper to ease the creation of
|
||||||
|
template tags that store results in a template variable. The
|
||||||
|
:meth:`~django.template.Library.simple_tag` helper has gained this same
|
||||||
|
ability, making the ``assignment_tag`` obsolete. Tags that use
|
||||||
|
``assignment_tag`` should be updated to use ``simple_tag``.
|
||||||
|
|
||||||
Miscellaneous
|
Miscellaneous
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import operator
|
import operator
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django import template
|
from django import template
|
||||||
from django.template.defaultfilters import stringfilter
|
from django.template.defaultfilters import stringfilter
|
||||||
|
@ -125,83 +126,17 @@ def minustwo_overridden_name(value):
|
||||||
register.simple_tag(lambda x: x - 1, name='minusone')
|
register.simple_tag(lambda x: x - 1, name='minusone')
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag
|
with warnings.catch_warnings():
|
||||||
def assignment_no_params():
|
warnings.simplefilter('ignore')
|
||||||
"""Expected assignment_no_params __doc__"""
|
|
||||||
return "assignment_no_params - Expected result"
|
|
||||||
assignment_no_params.anything = "Expected assignment_no_params __dict__"
|
|
||||||
|
|
||||||
|
@register.assignment_tag
|
||||||
|
def assignment_no_params():
|
||||||
|
"""Expected assignment_no_params __doc__"""
|
||||||
|
return "assignment_no_params - Expected result"
|
||||||
|
assignment_no_params.anything = "Expected assignment_no_params __dict__"
|
||||||
|
|
||||||
@register.assignment_tag
|
@register.assignment_tag(takes_context=True)
|
||||||
def assignment_one_param(arg):
|
def assignment_tag_without_context_parameter(arg):
|
||||||
"""Expected assignment_one_param __doc__"""
|
"""Expected assignment_tag_without_context_parameter __doc__"""
|
||||||
return "assignment_one_param - Expected result: %s" % arg
|
return "Expected result"
|
||||||
assignment_one_param.anything = "Expected assignment_one_param __dict__"
|
assignment_tag_without_context_parameter.anything = "Expected assignment_tag_without_context_parameter __dict__"
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=False)
|
|
||||||
def assignment_explicit_no_context(arg):
|
|
||||||
"""Expected assignment_explicit_no_context __doc__"""
|
|
||||||
return "assignment_explicit_no_context - Expected result: %s" % arg
|
|
||||||
assignment_explicit_no_context.anything = "Expected assignment_explicit_no_context __dict__"
|
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
|
||||||
def assignment_no_params_with_context(context):
|
|
||||||
"""Expected assignment_no_params_with_context __doc__"""
|
|
||||||
return "assignment_no_params_with_context - Expected result (context value: %s)" % context['value']
|
|
||||||
assignment_no_params_with_context.anything = "Expected assignment_no_params_with_context __dict__"
|
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
|
||||||
def assignment_params_and_context(context, arg):
|
|
||||||
"""Expected assignment_params_and_context __doc__"""
|
|
||||||
return "assignment_params_and_context - Expected result (context value: %s): %s" % (context['value'], arg)
|
|
||||||
assignment_params_and_context.anything = "Expected assignment_params_and_context __dict__"
|
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag
|
|
||||||
def assignment_two_params(one, two):
|
|
||||||
"""Expected assignment_two_params __doc__"""
|
|
||||||
return "assignment_two_params - Expected result: %s, %s" % (one, two)
|
|
||||||
assignment_two_params.anything = "Expected assignment_two_params __dict__"
|
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag
|
|
||||||
def assignment_one_default(one, two='hi'):
|
|
||||||
"""Expected assignment_one_default __doc__"""
|
|
||||||
return "assignment_one_default - Expected result: %s, %s" % (one, two)
|
|
||||||
assignment_one_default.anything = "Expected assignment_one_default __dict__"
|
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag
|
|
||||||
def assignment_unlimited_args(one, two='hi', *args):
|
|
||||||
"""Expected assignment_unlimited_args __doc__"""
|
|
||||||
return "assignment_unlimited_args - Expected result: %s" % (', '.join(six.text_type(arg) for arg in [one, two] + list(args)))
|
|
||||||
assignment_unlimited_args.anything = "Expected assignment_unlimited_args __dict__"
|
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag
|
|
||||||
def assignment_only_unlimited_args(*args):
|
|
||||||
"""Expected assignment_only_unlimited_args __doc__"""
|
|
||||||
return "assignment_only_unlimited_args - Expected result: %s" % ', '.join(six.text_type(arg) for arg in args)
|
|
||||||
assignment_only_unlimited_args.anything = "Expected assignment_only_unlimited_args __dict__"
|
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag
|
|
||||||
def assignment_unlimited_args_kwargs(one, two='hi', *args, **kwargs):
|
|
||||||
"""Expected assignment_unlimited_args_kwargs __doc__"""
|
|
||||||
# Sort the dictionary by key to guarantee the order for testing.
|
|
||||||
sorted_kwarg = sorted(six.iteritems(kwargs), key=operator.itemgetter(0))
|
|
||||||
return "assignment_unlimited_args_kwargs - Expected result: %s / %s" % (
|
|
||||||
', '.join(six.text_type(arg) for arg in [one, two] + list(args)),
|
|
||||||
', '.join('%s=%s' % (k, v) for (k, v) in sorted_kwarg)
|
|
||||||
)
|
|
||||||
assignment_unlimited_args_kwargs.anything = "Expected assignment_unlimited_args_kwargs __dict__"
|
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
|
||||||
def assignment_tag_without_context_parameter(arg):
|
|
||||||
"""Expected assignment_tag_without_context_parameter __doc__"""
|
|
||||||
return "Expected result"
|
|
||||||
assignment_tag_without_context_parameter.anything = "Expected assignment_tag_without_context_parameter __dict__"
|
|
||||||
|
|
|
@ -28,70 +28,61 @@ class CustomTagTests(TestCase):
|
||||||
def test_simple_tags(self):
|
def test_simple_tags(self):
|
||||||
c = template.Context({'value': 42})
|
c = template.Context({'value': 42})
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% no_params %}')
|
templates = [
|
||||||
self.assertEqual(t.render(c), 'no_params - Expected result')
|
('{% load custom %}{% no_params %}', 'no_params - Expected result'),
|
||||||
|
('{% load custom %}{% one_param 37 %}', 'one_param - Expected result: 37'),
|
||||||
|
('{% load custom %}{% explicit_no_context 37 %}', 'explicit_no_context - Expected result: 37'),
|
||||||
|
('{% load custom %}{% no_params_with_context %}',
|
||||||
|
'no_params_with_context - Expected result (context value: 42)'),
|
||||||
|
('{% load custom %}{% params_and_context 37 %}',
|
||||||
|
'params_and_context - Expected result (context value: 42): 37'),
|
||||||
|
('{% load custom %}{% simple_two_params 37 42 %}', 'simple_two_params - Expected result: 37, 42'),
|
||||||
|
('{% load custom %}{% simple_one_default 37 %}', 'simple_one_default - Expected result: 37, hi'),
|
||||||
|
('{% load custom %}{% simple_one_default 37 two="hello" %}',
|
||||||
|
'simple_one_default - Expected result: 37, hello'),
|
||||||
|
('{% load custom %}{% simple_one_default one=99 two="hello" %}',
|
||||||
|
'simple_one_default - Expected result: 99, hello'),
|
||||||
|
('{% load custom %}{% simple_one_default 37 42 %}',
|
||||||
|
'simple_one_default - Expected result: 37, 42'),
|
||||||
|
('{% load custom %}{% simple_unlimited_args 37 %}', 'simple_unlimited_args - Expected result: 37, hi'),
|
||||||
|
('{% load custom %}{% simple_unlimited_args 37 42 56 89 %}',
|
||||||
|
'simple_unlimited_args - Expected result: 37, 42, 56, 89'),
|
||||||
|
('{% load custom %}{% simple_only_unlimited_args %}', 'simple_only_unlimited_args - Expected result: '),
|
||||||
|
('{% load custom %}{% simple_only_unlimited_args 37 42 56 89 %}',
|
||||||
|
'simple_only_unlimited_args - Expected result: 37, 42, 56, 89'),
|
||||||
|
('{% load custom %}{% simple_unlimited_args_kwargs 37 40|add:2 56 eggs="scrambled" four=1|add:3 %}',
|
||||||
|
'simple_unlimited_args_kwargs - Expected result: 37, 42, 56 / eggs=scrambled, four=4'),
|
||||||
|
]
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% one_param 37 %}')
|
for entry in templates:
|
||||||
self.assertEqual(t.render(c), 'one_param - Expected result: 37')
|
t = template.Template(entry[0])
|
||||||
|
self.assertEqual(t.render(c), entry[1])
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% explicit_no_context 37 %}')
|
for entry in templates:
|
||||||
self.assertEqual(t.render(c), 'explicit_no_context - Expected result: 37')
|
t = template.Template("%s as var %%}Result: {{ var }}" % entry[0][0:-2])
|
||||||
|
self.assertEqual(t.render(c), "Result: %s" % entry[1])
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% no_params_with_context %}')
|
def test_simple_tag_errors(self):
|
||||||
self.assertEqual(t.render(c), 'no_params_with_context - Expected result (context value: 42)')
|
errors = [
|
||||||
|
("'simple_one_default' received unexpected keyword argument 'three'",
|
||||||
|
'{% load custom %}{% simple_one_default 99 two="hello" three="foo" %}'),
|
||||||
|
("'simple_two_params' received too many positional arguments",
|
||||||
|
'{% load custom %}{% simple_two_params 37 42 56 %}'),
|
||||||
|
("'simple_one_default' received too many positional arguments",
|
||||||
|
'{% load custom %}{% simple_one_default 37 42 56 %}'),
|
||||||
|
("'simple_unlimited_args_kwargs' received some positional argument\(s\) after some keyword argument\(s\)",
|
||||||
|
'{% load custom %}{% simple_unlimited_args_kwargs 37 40|add:2 eggs="scrambled" 56 four=1|add:3 %}'),
|
||||||
|
("'simple_unlimited_args_kwargs' received multiple values for keyword argument 'eggs'",
|
||||||
|
'{% load custom %}{% simple_unlimited_args_kwargs 37 eggs="scrambled" eggs="scrambled" %}'),
|
||||||
|
]
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% params_and_context 37 %}')
|
for entry in errors:
|
||||||
self.assertEqual(t.render(c), 'params_and_context - Expected result (context value: 42): 37')
|
six.assertRaisesRegex(self, template.TemplateSyntaxError, entry[0], template.Template, entry[1])
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% simple_two_params 37 42 %}')
|
for entry in errors:
|
||||||
self.assertEqual(t.render(c), 'simple_two_params - Expected result: 37, 42')
|
six.assertRaisesRegex(
|
||||||
|
self, template.TemplateSyntaxError, entry[0], template.Template, "%s as var %%}" % entry[1][0:-2],
|
||||||
t = template.Template('{% load custom %}{% simple_one_default 37 %}')
|
)
|
||||||
self.assertEqual(t.render(c), 'simple_one_default - Expected result: 37, hi')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% simple_one_default 37 two="hello" %}')
|
|
||||||
self.assertEqual(t.render(c), 'simple_one_default - Expected result: 37, hello')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% simple_one_default one=99 two="hello" %}')
|
|
||||||
self.assertEqual(t.render(c), 'simple_one_default - Expected result: 99, hello')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'simple_one_default' received unexpected keyword argument 'three'",
|
|
||||||
template.Template, '{% load custom %}{% simple_one_default 99 two="hello" three="foo" %}')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% simple_one_default 37 42 %}')
|
|
||||||
self.assertEqual(t.render(c), 'simple_one_default - Expected result: 37, 42')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% simple_unlimited_args 37 %}')
|
|
||||||
self.assertEqual(t.render(c), 'simple_unlimited_args - Expected result: 37, hi')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% simple_unlimited_args 37 42 56 89 %}')
|
|
||||||
self.assertEqual(t.render(c), 'simple_unlimited_args - Expected result: 37, 42, 56, 89')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% simple_only_unlimited_args %}')
|
|
||||||
self.assertEqual(t.render(c), 'simple_only_unlimited_args - Expected result: ')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% simple_only_unlimited_args 37 42 56 89 %}')
|
|
||||||
self.assertEqual(t.render(c), 'simple_only_unlimited_args - Expected result: 37, 42, 56, 89')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'simple_two_params' received too many positional arguments",
|
|
||||||
template.Template, '{% load custom %}{% simple_two_params 37 42 56 %}')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'simple_one_default' received too many positional arguments",
|
|
||||||
template.Template, '{% load custom %}{% simple_one_default 37 42 56 %}')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% simple_unlimited_args_kwargs 37 40|add:2 56 eggs="scrambled" four=1|add:3 %}')
|
|
||||||
self.assertEqual(t.render(c), 'simple_unlimited_args_kwargs - Expected result: 37, 42, 56 / eggs=scrambled, four=4')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'simple_unlimited_args_kwargs' received some positional argument\(s\) after some keyword argument\(s\)",
|
|
||||||
template.Template, '{% load custom %}{% simple_unlimited_args_kwargs 37 40|add:2 eggs="scrambled" 56 four=1|add:3 %}')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'simple_unlimited_args_kwargs' received multiple values for keyword argument 'eggs'",
|
|
||||||
template.Template, '{% load custom %}{% simple_unlimited_args_kwargs 37 eggs="scrambled" eggs="scrambled" %}')
|
|
||||||
|
|
||||||
def test_simple_tag_registration(self):
|
def test_simple_tag_registration(self):
|
||||||
# Test that the decorators preserve the decorated function's docstring, name and attributes.
|
# Test that the decorators preserve the decorated function's docstring, name and attributes.
|
||||||
|
@ -278,102 +269,9 @@ class CustomTagTests(TestCase):
|
||||||
t = template.Template('{% load custom %}{% assignment_no_params as var %}The result is: {{ var }}')
|
t = template.Template('{% load custom %}{% assignment_no_params as var %}The result is: {{ var }}')
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_no_params - Expected result')
|
self.assertEqual(t.render(c), 'The result is: assignment_no_params - Expected result')
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_one_param 37 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_one_param - Expected result: 37')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_explicit_no_context 37 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_explicit_no_context - Expected result: 37')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_no_params_with_context as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_no_params_with_context - Expected result (context value: 42)')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_params_and_context 37 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_params_and_context - Expected result (context value: 42): 37')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_two_params 37 42 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_two_params - Expected result: 37, 42')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_one_default 37 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_one_default - Expected result: 37, hi')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_one_default 37 two="hello" as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_one_default - Expected result: 37, hello')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_one_default one=99 two="hello" as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_one_default - Expected result: 99, hello')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_one_default' received unexpected keyword argument 'three'",
|
|
||||||
template.Template, '{% load custom %}{% assignment_one_default 99 two="hello" three="foo" as var %}')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_one_default 37 42 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_one_default - Expected result: 37, 42')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_unlimited_args 37 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_unlimited_args - Expected result: 37, hi')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_unlimited_args 37 42 56 89 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_unlimited_args - Expected result: 37, 42, 56, 89')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_only_unlimited_args as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_only_unlimited_args - Expected result: ')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_only_unlimited_args 37 42 56 89 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_only_unlimited_args - Expected result: 37, 42, 56, 89')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_one_param' tag takes at least 2 arguments and the second last argument must be 'as'",
|
|
||||||
template.Template, '{% load custom %}{% assignment_one_param 37 %}The result is: {{ var }}')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_one_param' tag takes at least 2 arguments and the second last argument must be 'as'",
|
|
||||||
template.Template, '{% load custom %}{% assignment_one_param 37 as %}The result is: {{ var }}')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_one_param' tag takes at least 2 arguments and the second last argument must be 'as'",
|
|
||||||
template.Template, '{% load custom %}{% assignment_one_param 37 ass var %}The result is: {{ var }}')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_two_params' received too many positional arguments",
|
|
||||||
template.Template, '{% load custom %}{% assignment_two_params 37 42 56 as var %}The result is: {{ var }}')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_one_default' received too many positional arguments",
|
|
||||||
template.Template, '{% load custom %}{% assignment_one_default 37 42 56 as var %}The result is: {{ var }}')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_one_default' did not receive value\(s\) for the argument\(s\): 'one'",
|
|
||||||
template.Template, '{% load custom %}{% assignment_one_default as var %}The result is: {{ var }}')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_unlimited_args' did not receive value\(s\) for the argument\(s\): 'one'",
|
|
||||||
template.Template, '{% load custom %}{% assignment_unlimited_args as var %}The result is: {{ var }}')
|
|
||||||
|
|
||||||
t = template.Template('{% load custom %}{% assignment_unlimited_args_kwargs 37 40|add:2 56 eggs="scrambled" four=1|add:3 as var %}The result is: {{ var }}')
|
|
||||||
self.assertEqual(t.render(c), 'The result is: assignment_unlimited_args_kwargs - Expected result: 37, 42, 56 / eggs=scrambled, four=4')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_unlimited_args_kwargs' received some positional argument\(s\) after some keyword argument\(s\)",
|
|
||||||
template.Template, '{% load custom %}{% assignment_unlimited_args_kwargs 37 40|add:2 eggs="scrambled" 56 four=1|add:3 as var %}The result is: {{ var }}')
|
|
||||||
|
|
||||||
six.assertRaisesRegex(self, template.TemplateSyntaxError,
|
|
||||||
"'assignment_unlimited_args_kwargs' received multiple values for keyword argument 'eggs'",
|
|
||||||
template.Template, '{% load custom %}{% assignment_unlimited_args_kwargs 37 eggs="scrambled" eggs="scrambled" as var %}The result is: {{ var }}')
|
|
||||||
|
|
||||||
def test_assignment_tag_registration(self):
|
def test_assignment_tag_registration(self):
|
||||||
# Test that the decorators preserve the decorated function's docstring, name and attributes.
|
# Test that the decorators preserve the decorated function's docstring, name and attributes.
|
||||||
self.verify_tag(custom.assignment_no_params, 'assignment_no_params')
|
self.verify_tag(custom.assignment_no_params, 'assignment_no_params')
|
||||||
self.verify_tag(custom.assignment_one_param, 'assignment_one_param')
|
|
||||||
self.verify_tag(custom.assignment_explicit_no_context, 'assignment_explicit_no_context')
|
|
||||||
self.verify_tag(custom.assignment_no_params_with_context, 'assignment_no_params_with_context')
|
|
||||||
self.verify_tag(custom.assignment_params_and_context, 'assignment_params_and_context')
|
|
||||||
self.verify_tag(custom.assignment_one_default, 'assignment_one_default')
|
|
||||||
self.verify_tag(custom.assignment_two_params, 'assignment_two_params')
|
|
||||||
self.verify_tag(custom.assignment_unlimited_args, 'assignment_unlimited_args')
|
|
||||||
self.verify_tag(custom.assignment_only_unlimited_args, 'assignment_only_unlimited_args')
|
|
||||||
self.verify_tag(custom.assignment_unlimited_args, 'assignment_unlimited_args')
|
|
||||||
self.verify_tag(custom.assignment_unlimited_args_kwargs, 'assignment_unlimited_args_kwargs')
|
|
||||||
self.verify_tag(custom.assignment_tag_without_context_parameter, 'assignment_tag_without_context_parameter')
|
|
||||||
|
|
||||||
def test_assignment_tag_missing_context(self):
|
def test_assignment_tag_missing_context(self):
|
||||||
# The 'context' parameter must be present when takes_context is True
|
# The 'context' parameter must be present when takes_context is True
|
||||||
|
|
Loading…
Reference in New Issue