Ticket #14908: 14908_simple_tag_takes_context_r14922.diff
File 14908_simple_tag_takes_context_r14922.diff, 7.3 KB (added by , 14 years ago) |
---|
-
django/template/base.py
805 805 return '' 806 806 return _render_value_in_context(output, context) 807 807 808 def generic_tag_compiler(params, defaults, name, node_class, parser, token ):808 def generic_tag_compiler(params, defaults, name, node_class, parser, token, takes_context=False): 809 809 "Returns a template.Node subclass." 810 810 bits = token.split_contents()[1:] 811 811 bmax = len(params) … … 817 817 else: 818 818 message = "%s takes between %s and %s arguments" % (name, bmin, bmax) 819 819 raise TemplateSyntaxError(message) 820 if takes_context: 821 node_class = curry(node_class, takes_context=takes_context) 820 822 return node_class(bits) 821 823 822 824 class Library(object): … … 872 874 self.filters[getattr(func, "_decorated_function", func).__name__] = func 873 875 return func 874 876 875 def simple_tag(self,func): 876 params, xx, xxx, defaults = getargspec(func) 877 def simple_tag(self, compile_function=None, takes_context=None): 878 def dec(func): 879 params, xx, xxx, defaults = getargspec(func) 880 if takes_context: 881 if params[0] == 'context': 882 params = params[1:] 883 else: 884 raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'") 885 886 class SimpleNode(Node): 887 def __init__(self, vars_to_resolve, takes_context=False): 888 self.vars_to_resolve = map(Variable, vars_to_resolve) 889 self.takes_context = takes_context 877 890 878 class SimpleNode(Node): 879 def __init__(self, vars_to_resolve): 880 self.vars_to_resolve = map(Variable, vars_to_resolve) 891 def render(self, context): 892 resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] 893 if self.takes_context: 894 func_args = [context] + resolved_vars 895 else: 896 func_args = resolved_vars 897 return func(*func_args) 898 compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode, takes_context=takes_context) 899 compile_func.__doc__ = func.__doc__ 900 self.tag(getattr(func, "_decorated_function", func).__name__, compile_func) 901 return func 902 903 if takes_context is not None: 904 # Example: @register.simple_tag(takes_context=True) 905 return dec 906 elif compile_function is None: 907 # @register.simple_tag() 908 return dec 909 elif callable(compile_function): 910 # @register.simple_tag 911 return dec(compile_function) 912 else: 913 raise TemplateSyntaxError("Incorrect parameters for the simple_tag decorator.") 881 914 882 def render(self, context):883 resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]884 return func(*resolved_vars)885 886 compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode)887 compile_func.__doc__ = func.__doc__888 self.tag(getattr(func, "_decorated_function", func).__name__, compile_func)889 return func890 891 915 def inclusion_tag(self, file_name, context_class=Context, takes_context=False): 892 916 def dec(func): 893 917 params, xx, xxx, defaults = getargspec(func) -
tests/regressiontests/templates/tests.py
22 22 from django.utils.safestring import mark_safe 23 23 from django.utils.tzinfo import LocalTimezone 24 24 25 from decorators import DecoratorsTest 25 26 from context import ContextTests 26 27 from custom import CustomTests 27 28 from parser import ParserTests -
tests/regressiontests/templates/decorators.py
1 from unittest import TestCase 2 from sys import version_info 3 4 from django import template 5 6 register = template.Library() 7 8 # Very simple tag, with no parameters. 9 def a_simple_tag_without_parameters(arg): 10 """Expected __doc__""" 11 return "Expected result" 12 a_simple_tag_without_parameters.anything = "Expected __dict__" 13 14 # Tag that takes the context. 15 def a_simple_tag_with_context(context, arg): 16 """Expected __doc__""" 17 return "Expected result" 18 a_simple_tag_with_context.anything = "Expected __dict__" 19 20 class DecoratorsTest(TestCase): 21 def verify_decorator(self, decorator, func_name): 22 self.assertEquals(decorator.__name__, func_name) 23 self.assertEquals(decorator.__doc__, 'Expected __doc__') 24 self.assertEquals(decorator.__dict__['anything'], 'Expected __dict__') 25 26 def test_simple_tag(self): 27 # Test that the decorators preserve the decorated function's docstring, name and attributes. 28 decorator = register.simple_tag(a_simple_tag_without_parameters) 29 self.verify_decorator(decorator, 'a_simple_tag_without_parameters') 30 31 decorator = register.simple_tag(takes_context=False)(a_simple_tag_without_parameters) 32 self.verify_decorator(decorator, 'a_simple_tag_without_parameters') 33 34 decorator = register.simple_tag(takes_context=True)(a_simple_tag_with_context) 35 self.verify_decorator(decorator, 'a_simple_tag_with_context') 36 37 # Test that the 'context' parameter is present when takes_context is True 38 decorator = register.simple_tag(takes_context=True) 39 self.assertRaises(template.TemplateSyntaxError, decorator, a_simple_tag_without_parameters) 40 -
docs/howto/custom-template-tags.txt
669 669 * If the argument was a template variable, our function is passed the 670 670 current value of the variable, not the variable itself. 671 671 672 When your template tag does not need access to the current context, writing a 673 function to work with the input values and using the ``simple_tag`` helper is 674 the easiest way to create a new tag. 672 If your template tag needs to access the current context, you can use the 673 ``takes_context`` option as follows:: 675 674 675 # The first argument *must* be called "context" here. 676 def current_time(context, format_string): 677 timezone = context['timezone'] 678 ... 679 680 register.simple_tag(takes_context=True)(current_time) 681 682 You may also use the decorator syntax:: 683 684 @register.simple_tag(takes_context=True) 685 def current_time(context, format_string): 686 ... 687 688 For more information on how the ``takes_context`` option works, see the section 689 on `inclusion tags`_. 690 676 691 .. _howto-custom-template-tags-inclusion-tags: 677 692 678 693 Inclusion tags