Ticket #7462: simple_tag_takes_context.diff

File simple_tag_takes_context.diff, 7.2 KB (added by Julien Phalip, 16 years ago)
  • E:/Software/workspace/django/django/template/__init__.py

     
    4949u'<html></html>'
    5050"""
    5151import re
    52 from inspect import getargspec
     52from inspect import getargspec, isfunction
    5353from django.conf import settings
    5454from django.template.context import Context, RequestContext, ContextPopException
    5555from django.utils.itercompat import is_iterable
     
    859859        self.filters[getattr(func, "_decorated_function", func).__name__] = func
    860860        return func
    861861
    862     def simple_tag(self,func):
    863         params, xx, xxx, defaults = getargspec(func)
     862    def simple_tag(self, *args, **kwargs):
     863        def dec(func):
     864            params, xx, xxx, defaults = getargspec(func)
     865            if takes_context:
     866                if params[0] == 'context':
     867                    params = params[1:]
     868                else:
     869                    raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'")
    864870
    865         class SimpleNode(Node):
    866             def __init__(self, vars_to_resolve):
    867                 self.vars_to_resolve = map(Variable, vars_to_resolve)
     871            class SimpleNode(Node):
     872                def __init__(self, vars_to_resolve):
     873                    self.vars_to_resolve = map(Variable, vars_to_resolve)
     874   
     875                def render(self, context):
     876                    resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
     877                    if takes_context:
     878                        func_args = [context] + resolved_vars
     879                    else:
     880                        func_args = resolved_vars
     881                    return func(*func_args)
    868882
    869             def render(self, context):
    870                 resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
    871                 return func(*resolved_vars)
     883            compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode)
     884            compile_func.__doc__ = func.__doc__
     885            self.tag(getattr(func, "_decorated_function", func).__name__, compile_func)
     886            return func
     887       
     888        if len(args) == 1 and len(kwargs) == 0 and isfunction(args[0]):
     889            takes_context = False
     890            return dec(args[0])
     891        elif len(args) == 0 and len(kwargs) == 0:
     892            takes_context = False
     893            return dec
     894        elif len(args) == 0 and len(kwargs) == 1 and 'takes_context' in kwargs:
     895            takes_context = kwargs['takes_context']
     896            return dec
     897        else:
     898            raise TemplateSyntaxError("Incorrect parameters for simple_tag")
    872899
    873         compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode)
    874         compile_func.__doc__ = func.__doc__
    875         self.tag(getattr(func, "_decorated_function", func).__name__, compile_func)
    876         return func
    877 
    878900    def inclusion_tag(self, file_name, context_class=Context, takes_context=False):
    879901        def dec(func):
    880902            params, xx, xxx, defaults = getargspec(func)
  • E:/Software/workspace/django/tests/regressiontests/templates/tests.py

     
    1717from django.utils.safestring import mark_safe
    1818from django.utils.tzinfo import LocalTimezone
    1919
     20from decorators import DecoratorsTest
    2021from unicode import unicode_tests
    2122from context import context_tests
    2223
  • E:/Software/workspace/django/tests/regressiontests/templates/decorators.py

     
     1from unittest import TestCase
     2from sys import version_info
     3
     4from django import template
     5
     6register = template.Library()
     7
     8def a_simple_tag(arg):
     9    """Expected __doc__"""
     10    return "Expected result"
     11a_simple_tag.anything = "Expected __dict__"
     12
     13a_simple_tag = register.simple_tag(a_simple_tag)
     14
     15
     16def a_simple_tag_with_context(context, arg):
     17    """Expected __doc__"""
     18    return "Expected result"
     19a_simple_tag_with_context.anything = "Expected __dict__"
     20
     21a_simple_tag_with_context = register.simple_tag(takes_context=True)(a_simple_tag_with_context)
     22
     23
     24
     25class DecoratorsTest(TestCase):
     26
     27    def test_simple_tag(self):
     28        # Only check __name__ on Python 2.4 or later since __name__ can't be
     29        # assigned to in earlier Python versions.
     30        if version_info[0] >= 2 and version_info[1] >= 4:
     31            self.assertEquals(a_simple_tag.__name__, 'a_simple_tag')
     32        self.assertEquals(a_simple_tag.__doc__, 'Expected __doc__')
     33        self.assertEquals(a_simple_tag.__dict__['anything'], 'Expected __dict__')
     34
     35
     36    def test_simple_tag_with_context(self):
     37        # Only check __name__ on Python 2.4 or later since __name__ can't be
     38        # assigned to in earlier Python versions.
     39        if version_info[0] >= 2 and version_info[1] >= 4:
     40            self.assertEquals(a_simple_tag_with_context.__name__, 'a_simple_tag_with_context')
     41        self.assertEquals(a_simple_tag_with_context.__doc__, 'Expected __doc__')
     42        self.assertEquals(a_simple_tag_with_context.__dict__['anything'], 'Expected __dict__')
     43 No newline at end of file
  • E:/Software/workspace/django/docs/templates_python.txt

     
    11691169In Python 2.4, the decorator syntax also works::
    11701170
    11711171    @register.simple_tag
    1172     def current_time(token):
     1172    def current_time(format_string):
    11731173        ...
    11741174
    11751175A couple of things to note about the ``simple_tag`` helper function:
     
    11841184function to work with the input values and using the ``simple_tag`` helper is
    11851185the easiest way to create a new tag.
    11861186
     1187If your template tag *does* need to access the current context, you can use the
     1188``takes_context`` option as follows::
     1189
     1190    # The first argument *must* be called "context" here.
     1191    def current_time(context, format_string):
     1192        timezone = context['timezone']
     1193        ...
     1194
     1195    register.simple_tag(takes_context=True)(current_time)
     1196
     1197You can also use the decorator syntax if running in Python 2.4::
     1198
     1199    @register.simple_tag(takes_context=True)
     1200    def current_time(context, format_string):
     1201
     1202For more information on how the ``takes_context`` option works, see the section
     1203on `inclusion tags`_.
     1204
     1205.. _inclusion tags: #inclusion-tags
     1206
    11871207Inclusion tags
    11881208~~~~~~~~~~~~~~
    11891209
Back to Top