=== modified file 'django/contrib/admin/templatetags/admin_modify.py'
|
|
|
|
| 71 | 71 | default = None |
| 72 | 72 | |
| 73 | 73 | def __init__(self, bound_field_var): |
| 74 | | self.bound_field_var = bound_field_var |
| | 74 | self.bound_field_var = template.Variable(bound_field_var) |
| 75 | 75 | |
| 76 | 76 | def get_nodelist(cls, klass): |
| 77 | 77 | if klass not in cls.nodelists: |
| … |
… |
|
| 95 | 95 | get_nodelist = classmethod(get_nodelist) |
| 96 | 96 | |
| 97 | 97 | def render(self, context): |
| 98 | | bound_field = template.resolve_variable(self.bound_field_var, context) |
| | 98 | bound_field = self.bound_field_var.resolve(context) |
| 99 | 99 | |
| 100 | 100 | context.push() |
| 101 | 101 | context['bound_field'] = bound_field |
| … |
… |
|
| 155 | 155 | |
| 156 | 156 | class EditInlineNode(template.Node): |
| 157 | 157 | def __init__(self, rel_var): |
| 158 | | self.rel_var = rel_var |
| | 158 | self.rel_var = template.Variable(rel_var) |
| 159 | 159 | |
| 160 | 160 | def render(self, context): |
| 161 | | relation = template.resolve_variable(self.rel_var, context) |
| | 161 | relation = self.rel_var.resolve(context) |
| 162 | 162 | context.push() |
| 163 | 163 | if relation.field.rel.edit_inline == models.TABULAR: |
| 164 | 164 | bound_related_object_class = TabularBoundRelatedObject |
=== modified file 'django/contrib/comments/templatetags/comments.py'
|
|
|
|
| 18 | 18 | ratings_optional=False, ratings_required=False, rating_options='', |
| 19 | 19 | is_public=True): |
| 20 | 20 | self.content_type = content_type |
| | 21 | if obj_id_lookup is not None: |
| | 22 | obj_id_lookup = template.Variable |
| 21 | 23 | self.obj_id_lookup_var, self.obj_id, self.free = obj_id_lookup_var, obj_id, free |
| 22 | 24 | self.photos_optional, self.photos_required = photos_optional, photos_required |
| 23 | 25 | self.ratings_optional, self.ratings_required = ratings_optional, ratings_required |
| … |
… |
|
| 31 | 33 | context.push() |
| 32 | 34 | if self.obj_id_lookup_var is not None: |
| 33 | 35 | try: |
| 34 | | self.obj_id = template.resolve_variable(self.obj_id_lookup_var, context) |
| | 36 | self.obj_id = self.obj_id_lookup_var.resolve(context) |
| 35 | 37 | except template.VariableDoesNotExist: |
| 36 | 38 | return '' |
| 37 | 39 | # Validate that this object ID is valid for this content-type. |
| … |
… |
|
| 74 | 76 | class CommentCountNode(template.Node): |
| 75 | 77 | def __init__(self, package, module, context_var_name, obj_id, var_name, free): |
| 76 | 78 | self.package, self.module = package, module |
| | 79 | if context_var_name is not None: |
| | 80 | context_var_name = template.Variable(context_var_name) |
| 77 | 81 | self.context_var_name, self.obj_id = context_var_name, obj_id |
| 78 | 82 | self.var_name, self.free = var_name, free |
| 79 | 83 | |
| … |
… |
|
| 81 | 85 | from django.conf import settings |
| 82 | 86 | manager = self.free and FreeComment.objects or Comment.objects |
| 83 | 87 | if self.context_var_name is not None: |
| 84 | | self.obj_id = template.resolve_variable(self.context_var_name, context) |
| | 88 | self.obj_id = self.context_var_name.resolve(context) |
| 85 | 89 | comment_count = manager.filter(object_id__exact=self.obj_id, |
| 86 | 90 | content_type__app_label__exact=self.package, |
| 87 | 91 | content_type__model__exact=self.module, site__id__exact=settings.SITE_ID).count() |
| … |
… |
|
| 91 | 95 | class CommentListNode(template.Node): |
| 92 | 96 | def __init__(self, package, module, context_var_name, obj_id, var_name, free, ordering, extra_kwargs=None): |
| 93 | 97 | self.package, self.module = package, module |
| | 98 | if context_var_name is not None: |
| | 99 | context_var_name = template.Variable(context_var_name) |
| 94 | 100 | self.context_var_name, self.obj_id = context_var_name, obj_id |
| 95 | 101 | self.var_name, self.free = var_name, free |
| 96 | 102 | self.ordering = ordering |
| … |
… |
|
| 101 | 107 | get_list_function = self.free and FreeComment.objects.filter or Comment.objects.get_list_with_karma |
| 102 | 108 | if self.context_var_name is not None: |
| 103 | 109 | try: |
| 104 | | self.obj_id = template.resolve_variable(self.context_var_name, context) |
| | 110 | self.obj_id = self.context_var_name.resolve(context) |
| 105 | 111 | except template.VariableDoesNotExist: |
| 106 | 112 | return '' |
| 107 | 113 | kwargs = { |
=== modified file 'django/template/__init__.py'
|
|
|
|
| 91 | 91 | tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END), |
| 92 | 92 | re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END), |
| 93 | 93 | re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END))) |
| 94 | | # matches if the string is valid number |
| 95 | | number_re = re.compile(r'[-+]?(\d+|\d*\.\d+)$') |
| 96 | 94 | |
| 97 | 95 | # global dictionary of libraries that have been loaded using get_library |
| 98 | 96 | libraries = {} |
| … |
… |
|
| 562 | 560 | elif constant_arg is not None: |
| 563 | 561 | args.append((False, constant_arg.replace(r'\"', '"'))) |
| 564 | 562 | elif var_arg: |
| 565 | | args.append((True, var_arg)) |
| | 563 | args.append((True, Variable(var_arg))) |
| 566 | 564 | filter_func = parser.find_filter(filter_name) |
| 567 | 565 | self.args_check(filter_name,filter_func, args) |
| 568 | 566 | filters.append( (filter_func,args)) |
| 569 | 567 | upto = match.end() |
| 570 | 568 | if upto != len(token): |
| 571 | 569 | raise TemplateSyntaxError, "Could not parse the remainder: '%s' from '%s'" % (token[upto:], token) |
| 572 | | self.var, self.filters = var, filters |
| | 570 | self.filters = filters |
| | 571 | self.var = Variable(var) |
| 573 | 572 | |
| 574 | 573 | def resolve(self, context, ignore_failures=False): |
| 575 | 574 | try: |
| 576 | | obj = resolve_variable(self.var, context) |
| | 575 | obj = self.var.resolve(context) |
| 577 | 576 | except VariableDoesNotExist: |
| 578 | 577 | if ignore_failures: |
| 579 | 578 | obj = None |
| … |
… |
|
| 593 | 592 | if not lookup: |
| 594 | 593 | arg_vals.append(arg) |
| 595 | 594 | else: |
| 596 | | arg_vals.append(resolve_variable(arg, context)) |
| | 595 | arg_vals.append(arg.resolve(context)) |
| 597 | 596 | obj = func(obj, *arg_vals) |
| 598 | 597 | return obj |
| 599 | 598 | |
| … |
… |
|
| 652 | 651 | |
| 653 | 652 | (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.') |
| 654 | 653 | """ |
| 655 | | if number_re.match(path): |
| 656 | | number_type = '.' in path and float or int |
| 657 | | current = number_type(path) |
| 658 | | elif path[0] in ('"', "'") and path[0] == path[-1]: |
| 659 | | current = path[1:-1] |
| 660 | | else: |
| | 654 | return Variable(path).resolve(context) |
| | 655 | |
| | 656 | class LiteralVariable(object): |
| | 657 | |
| | 658 | def __init__(self, val): |
| | 659 | self.val = val |
| | 660 | |
| | 661 | def resolve(self, context): |
| | 662 | return self.val |
| | 663 | |
| | 664 | def __str__(self): |
| | 665 | return self.val |
| | 666 | |
| | 667 | def Variable(val): |
| | 668 | try: |
| | 669 | # note we're not catching OverflowError here; point of debate on how best to handle that... |
| | 670 | current = float(val) |
| | 671 | if '.' not in val: |
| | 672 | # downside to this approach is that 1e07 becomes an int; float may be preferable still. |
| | 673 | current = int(current) |
| | 674 | elif val[-1] == '.': |
| | 675 | # 2. is invalid |
| | 676 | raise ValueError |
| | 677 | return LiteralVariable(current) |
| | 678 | except ValueError: |
| | 679 | pass |
| | 680 | if val[0] in "\"'" and val[0] == val[-1]: |
| | 681 | return LiteralVariable(val[1:-1]) |
| | 682 | return ChainedLookupVariable(val) |
| | 683 | |
| | 684 | class ChainedLookupVariable(object): |
| | 685 | |
| | 686 | def __init__(self, val): |
| | 687 | self.lookups = tuple(val.split(VARIABLE_ATTRIBUTE_SEPARATOR)) |
| | 688 | |
| | 689 | def resolve(self, context): |
| 661 | 690 | current = context |
| 662 | | bits = path.split(VARIABLE_ATTRIBUTE_SEPARATOR) |
| 663 | | while bits: |
| | 691 | for bit in self.lookups: |
| 664 | 692 | try: # dictionary lookup |
| 665 | | current = current[bits[0]] |
| | 693 | current = current[bit] |
| 666 | 694 | except (TypeError, AttributeError, KeyError): |
| 667 | 695 | try: # attribute lookup |
| 668 | | current = getattr(current, bits[0]) |
| | 696 | current = getattr(current, bit) |
| 669 | 697 | if callable(current): |
| 670 | 698 | if getattr(current, 'alters_data', False): |
| 671 | 699 | current = settings.TEMPLATE_STRING_IF_INVALID |
| … |
… |
|
| 683 | 711 | raise |
| 684 | 712 | except (TypeError, AttributeError): |
| 685 | 713 | try: # list-index lookup |
| 686 | | current = current[int(bits[0])] |
| | 714 | current = current[int(bit)] |
| 687 | 715 | except (IndexError, # list index out of range |
| 688 | 716 | ValueError, # invalid literal for int() |
| 689 | | KeyError, # current is a dict without `int(bits[0])` key |
| | 717 | KeyError, # current is a dict without `int(bit)` key |
| 690 | 718 | TypeError, # unsubscriptable object |
| 691 | 719 | ): |
| 692 | | raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bits[0], current)) # missing attribute |
| | 720 | raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bit, current)) # missing attribute |
| 693 | 721 | except Exception, e: |
| 694 | 722 | if getattr(e, 'silent_variable_failure', False): |
| 695 | 723 | current = settings.TEMPLATE_STRING_IF_INVALID |
| 696 | 724 | else: |
| 697 | 725 | raise |
| 698 | | del bits[0] |
| 699 | | return current |
| | 726 | return current |
| | 727 | |
| | 728 | def __str__(self): |
| | 729 | return VARIABLE_ATTRIBUTE_SEPARATOR.join(self.lookups) |
| 700 | 730 | |
| 701 | 731 | class Node(object): |
| 702 | 732 | def render(self, context): |
| … |
… |
|
| 867 | 897 | |
| 868 | 898 | class SimpleNode(Node): |
| 869 | 899 | def __init__(self, vars_to_resolve): |
| 870 | | self.vars_to_resolve = vars_to_resolve |
| | 900 | self.vars_to_resolve = map(Variable, vars_to_resolve) |
| 871 | 901 | |
| 872 | 902 | def render(self, context): |
| 873 | | resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] |
| 874 | | return func(*resolved_vars) |
| | 903 | return func(*[var.resolve(context) for var in self.vars_to_resolve]) |
| 875 | 904 | |
| 876 | 905 | compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode) |
| 877 | 906 | compile_func.__doc__ = func.__doc__ |
| … |
… |
|
| 889 | 918 | |
| 890 | 919 | class InclusionNode(Node): |
| 891 | 920 | def __init__(self, vars_to_resolve): |
| 892 | | self.vars_to_resolve = vars_to_resolve |
| | 921 | self.vars_to_resolve = map(Variable, vars_to_resolve) |
| 893 | 922 | |
| 894 | 923 | def render(self, context): |
| 895 | | resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] |
| | 924 | resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] |
| 896 | 925 | if takes_context: |
| 897 | 926 | args = [context] + resolved_vars |
| 898 | 927 | else: |
=== modified file 'django/template/defaulttags.py'
|
|
|
|
| 1 | 1 | "Default tags used by the template system, available to all templates." |
| 2 | 2 | |
| 3 | | from django.template import Node, NodeList, Template, Context, resolve_variable |
| | 3 | from django.template import Node, NodeList, Template, Context, Variable |
| 4 | 4 | from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END |
| 5 | 5 | from django.template import get_library, Library, InvalidTemplateLibrary |
| 6 | 6 | from django.conf import settings |
| … |
… |
|
| 48 | 48 | |
| 49 | 49 | class FirstOfNode(Node): |
| 50 | 50 | def __init__(self, vars): |
| 51 | | self.vars = vars |
| | 51 | self.vars = map(Variable, vars) |
| 52 | 52 | |
| 53 | 53 | def render(self, context): |
| 54 | 54 | for var in self.vars: |
| 55 | 55 | try: |
| 56 | | value = resolve_variable(var, context) |
| | 56 | value = var.resolve(context) |
| 57 | 57 | except VariableDoesNotExist: |
| 58 | 58 | continue |
| 59 | 59 | if value: |
| … |
… |
|
| 130 | 130 | def __init__(self, nodelist, *varlist): |
| 131 | 131 | self.nodelist = nodelist |
| 132 | 132 | self._last_seen = None |
| 133 | | self._varlist = varlist |
| | 133 | self._varlist = map(Variable, varlist) |
| 134 | 134 | |
| 135 | 135 | def render(self, context): |
| 136 | 136 | if 'forloop' in context and context['forloop']['first']: |
| … |
… |
|
| 139 | 139 | if self._varlist: |
| 140 | 140 | # Consider multiple parameters. |
| 141 | 141 | # This automatically behaves like a OR evaluation of the multiple variables. |
| 142 | | compare_to = [resolve_variable(var, context) for var in self._varlist] |
| | 142 | compare_to = [var.resolve(context) for var in self._varlist] |
| 143 | 143 | else: |
| 144 | 144 | compare_to = self.nodelist.render(context) |
| 145 | 145 | except VariableDoesNotExist: |
| … |
… |
|
| 158 | 158 | |
| 159 | 159 | class IfEqualNode(Node): |
| 160 | 160 | def __init__(self, var1, var2, nodelist_true, nodelist_false, negate): |
| 161 | | self.var1, self.var2 = var1, var2 |
| | 161 | self.var1, self.var2 = Variable(var1), Variable(var2) |
| 162 | 162 | self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false |
| 163 | 163 | self.negate = negate |
| 164 | 164 | |
| … |
… |
|
| 167 | 167 | |
| 168 | 168 | def render(self, context): |
| 169 | 169 | try: |
| 170 | | val1 = resolve_variable(self.var1, context) |
| | 170 | val1 = self.var1.resolve(context) |
| 171 | 171 | except VariableDoesNotExist: |
| 172 | 172 | val1 = None |
| 173 | 173 | try: |
| 174 | | val2 = resolve_variable(self.var2, context) |
| | 174 | val2 = self.var2.resolve(context) |
| 175 | 175 | except VariableDoesNotExist: |
| 176 | 176 | val2 = None |
| 177 | 177 | if (self.negate and val1 != val2) or (not self.negate and val1 == val2): |
=== modified file 'django/template/loader_tags.py'
|
|
|
|
| 1 | | from django.template import TemplateSyntaxError, TemplateDoesNotExist, resolve_variable |
| | 1 | from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable |
| 2 | 2 | from django.template import Library, Node |
| 3 | 3 | from django.template.loader import get_template, get_template_from_string, find_template_source |
| 4 | 4 | from django.conf import settings |
| … |
… |
|
| 99 | 99 | |
| 100 | 100 | class IncludeNode(Node): |
| 101 | 101 | def __init__(self, template_name): |
| 102 | | self.template_name = template_name |
| | 102 | self.template_name = Variable(template_name) |
| 103 | 103 | |
| 104 | 104 | def render(self, context): |
| 105 | 105 | try: |
| 106 | | template_name = resolve_variable(self.template_name, context) |
| | 106 | template_name = self.template_name.resolve(context) |
| 107 | 107 | t = get_template(template_name) |
| 108 | 108 | return t.render(context) |
| 109 | 109 | except TemplateSyntaxError, e: |
=== modified file 'django/templatetags/i18n.py'
|
|
|
|
| 1 | | from django.template import Node, resolve_variable |
| | 1 | from django.template import Node, Variable |
| 2 | 2 | from django.template import TemplateSyntaxError, TokenParser, Library |
| 3 | 3 | from django.template import TOKEN_TEXT, TOKEN_VAR |
| 4 | 4 | from django.utils import translation |
| … |
… |
|
| 32 | 32 | |
| 33 | 33 | class TranslateNode(Node): |
| 34 | 34 | def __init__(self, value, noop): |
| 35 | | self.value = value |
| | 35 | self.value = Variable(value) |
| 36 | 36 | self.noop = noop |
| 37 | 37 | |
| 38 | 38 | def render(self, context): |
| 39 | | value = resolve_variable(self.value, context) |
| | 39 | value = self.value.resolve(context) |
| 40 | 40 | if self.noop: |
| 41 | 41 | return value |
| 42 | 42 | else: |