Permalink
Browse files

Fixed #911 -- Made template system scoped to the parser instead of th…

…e template module. Also changed the way tags/filters are registered and added support for multiple arguments to {% load %} tag. Thanks, rjwittams. This is a backwards-incompatible change for people who've created custom template tags or filters. See http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges for upgrade instructions.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@1443 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent 5676d5b commit 3ede006fc98f7e96ae9fb997872f78635576d5f8 @adrianholovaty adrianholovaty committed Nov 26, 2005
Showing with 785 additions and 586 deletions.
  1. +1 −3 django/contrib/admin/templates/admin/change_form.html
  2. +1 −2 django/contrib/admin/templates/admin/change_list.html
  3. +1 −0 django/contrib/admin/templates/admin/edit_inline_stacked.html
  4. +1 −0 django/contrib/admin/templates/admin/edit_inline_tabular.html
  5. +1 −0 django/contrib/admin/templates/admin/field_line.html
  6. +1 −0 django/contrib/admin/templates/admin/filter.html
  7. +1 −0 django/contrib/admin/templates/admin/filters.html
  8. +1 −0 django/contrib/admin/templates/admin/pagination.html
  9. +1 −0 django/contrib/admin/templates/admin/search_form.html
  10. +1 −1 django/contrib/admin/templates/widget/default.html
  11. +1 −1 django/contrib/admin/templates/widget/file.html
  12. +2 −1 django/contrib/admin/templates/widget/foreign.html
  13. +17 −15 django/contrib/admin/templatetags/admin_list.py
  14. +19 −18 django/contrib/admin/templatetags/admin_modify.py
  15. +3 −1 django/contrib/admin/templatetags/adminapplist.py
  16. +3 −2 django/contrib/admin/templatetags/adminmedia.py
  17. +3 −1 django/contrib/admin/templatetags/log.py
  18. +7 −5 django/contrib/admin/views/template.py
  19. +8 −6 django/contrib/comments/templatetags/comments.py
  20. +14 −12 django/contrib/markup/templatetags/markup.py
  21. +238 −64 django/core/template/__init__.py
  22. +0 −67 django/core/template/decorators.py
  23. +83 −79 django/core/template/defaultfilters.py
  24. +90 −88 django/core/template/defaulttags.py
  25. +2 −167 django/core/template/loader.py
  26. +172 −0 django/core/template/loader_tags.py
  27. +12 −10 django/templatetags/i18n.py
  28. +5 −0 docs/templates.txt
  29. +65 −25 docs/templates_python.txt
  30. +6 −6 tests/othertests/defaultfilters.py
  31. +7 −6 tests/othertests/markup.py
  32. +14 −4 tests/othertests/templates.py
  33. +4 −2 tests/testapp/templatetags/testtags.py
@@ -1,7 +1,5 @@
{% extends "admin/base_site" %}
-{% load i18n %}
-{% load admin_modify %}
-{% load adminmedia %}
+{% load i18n admin_modify adminmedia %}
{% block extrahead %}
{% for js in bound_manipulator.javascript_imports %}{% include_admin_script js %}{% endfor %}
{% endblock %}
@@ -1,5 +1,4 @@
-{% load admin_list %}
-{% load i18n %}
+{% load adminmedia admin_list i18n %}
{% extends "admin/base_site" %}
{% block bodyclass %}change-list{% endblock %}
{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> &rsaquo; {{ cl.opts.verbose_name_plural|capfirst }} </div>{% endblock %}{% endif %}
@@ -1,3 +1,4 @@
+{% load admin_modify %}
<fieldset class="module aligned">
{% for fcw in bound_related_object.form_field_collection_wrappers %}
<h2>{{ bound_related_object.relation.opts.verbose_name|capfirst }}&nbsp;#{{ forloop.counter }}</h2>
@@ -1,3 +1,4 @@
+{% load admin_modify %}
<fieldset class="module">
<h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst }}</h2><table>
<thead><tr>
@@ -1,3 +1,4 @@
+{% load admin_modify %}
<div class="{{ class_names }}" >
{% for bound_field in bound_fields %}{{ bound_field.html_error_list }}{% endfor %}
{% for bound_field in bound_fields %}
@@ -1,3 +1,4 @@
+{% load i18n %}
<h3>{% blocktrans %} By {{ title }} {% endblocktrans %}</h3>
<ul>
{% for choice in choices %}
@@ -1,3 +1,4 @@
+{% load admin_list %}
{% if cl.has_filters %}<div id="changelist-filter">
<h2>Filter</h2>
{% for spec in cl.filter_specs %}
@@ -1,3 +1,4 @@
+{% load admin_list %}
<p class="paginator">
{% if pagination_required %}
{% for i in page_range %}
@@ -1,3 +1,4 @@
+{% load adminmedia %}
{% if cl.lookup_opts.admin.search_fields %}
<div id="toolbar"><form id="changelist-search" action="" method="get">
<label><img src="{% admin_media_prefix %}img/admin/icon_searchbox.png" /></label>
@@ -1 +1 @@
-{% output_all bound_field.form_fields %}
+{% load admin_modify %}{% output_all bound_field.form_fields %}
@@ -1,4 +1,4 @@
-{% if bound_field.original_value %}
+{% load admin_modify %}{% if bound_field.original_value %}
Currently: <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value }} </a><br />
Change: {% output_all bound_field.form_fields %}
{% else %} {% output_all bound_field.form_fields %} {% endif %}
@@ -1,7 +1,8 @@
+{% load admin_modify adminmedia %}
{% output_all bound_field.form_fields %}
{% if bound_field.raw_id_admin %}
<a href="../../../{{ bound_field.field.rel.to.app_label }}/{{ bound_field.field.rel.to.module_name }}/" class="related-lookup" id="lookup_{{bound_field.element_id}}" onclick="return showRelatedObjectLookupPopup(this);"> <img src="{% admin_media_prefix %}img/admin/selector-search.gif" width="16" height="16" alt="Lookup"></a>
{% else %}
{% if bound_field.needs_add_label %}
<a href="../../../{{ bound_field.field.rel.to.app_label }}/{{ bound_field.field.rel.to.module_name }}/add/" class="add-another" id="add_{{ bound_field.element_id}}" onclick="return showAddAnotherPopup(this);"> <img src="{% admin_media_prefix %}img/admin/icon_addlink.gif" width="10" height="10" alt="Add Another"/></a>
-{% endif %} {% endif %}
+{% endif %}{% endif %}
@@ -3,26 +3,28 @@
from django.contrib.admin.views.main import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE, MONTHS
from django.core import meta, template
from django.core.exceptions import ObjectDoesNotExist
-from django.core.template.decorators import simple_tag, inclusion_tag
from django.utils import dateformat
from django.utils.html import strip_tags, escape
from django.utils.text import capfirst
from django.utils.translation import get_date_formats
from django.conf.settings import ADMIN_MEDIA_PREFIX
+from django.core.template import Library
+
+register = Library()
DOT = '.'
-#@simple_tag
+#@register.simple_tag
def paginator_number(cl,i):
if i == DOT:
return '... '
elif i == cl.page_num:
return '<span class="this-page">%d</span> ' % (i+1)
else:
return '<a href="%s"%s>%d</a> ' % (cl.get_query_string({PAGE_VAR: i}), (i == cl.paginator.pages-1 and ' class="end"' or ''), i+1)
-paginator_number = simple_tag(paginator_number)
+paginator_number = register.simple_tag(paginator_number)
-#@inclusion_tag('admin/pagination')
+#@register.inclusion_tag('admin/pagination')
def pagination(cl):
paginator, page_num = cl.paginator, cl.page_num
@@ -64,7 +66,7 @@ def pagination(cl):
'ALL_VAR': ALL_VAR,
'1': 1,
}
-pagination = inclusion_tag('admin/pagination')(pagination)
+pagination = register.inclusion_tag('admin/pagination')(pagination)
def result_headers(cl):
lookup_opts = cl.lookup_opts
@@ -177,15 +179,15 @@ def results(cl):
for res in cl.result_list:
yield list(items_for_result(cl,res))
-#@inclusion_tag("admin/change_list_results")
+#@register.inclusion_tag("admin/change_list_results")
def result_list(cl):
res = list(results(cl))
return {'cl': cl,
'result_headers': list(result_headers(cl)),
'results': list(results(cl))}
-result_list = inclusion_tag("admin/change_list_results")(result_list)
+result_list = register.inclusion_tag("admin/change_list_results")(result_list)
-#@inclusion_tag("admin/date_hierarchy")
+#@register.inclusion_tag("admin/date_hierarchy")
def date_hierarchy(cl):
lookup_opts, params, lookup_params, lookup_mod = \
cl.lookup_opts, cl.params, cl.lookup_params, cl.lookup_mod
@@ -256,23 +258,23 @@ def get_dates(unit, params):
'title': year.year
} for year in years ]
}
-date_hierarchy = inclusion_tag('admin/date_hierarchy')(date_hierarchy)
+date_hierarchy = register.inclusion_tag('admin/date_hierarchy')(date_hierarchy)
-#@inclusion_tag('admin/search_form')
+#@register.inclusion_tag('admin/search_form')
def search_form(cl):
return {
'cl': cl,
'show_result_count': cl.result_count != cl.full_result_count and not cl.opts.one_to_one_field,
'search_var': SEARCH_VAR
}
-search_form = inclusion_tag('admin/search_form')(search_form)
+search_form = register.inclusion_tag('admin/search_form')(search_form)
-#@inclusion_tag('admin/filter')
+#@register.inclusion_tag('admin/filter')
def filter(cl, spec):
return {'title': spec.title(), 'choices' : list(spec.choices(cl))}
-filter = inclusion_tag('admin/filter')(filter)
+filter = register.inclusion_tag('admin/filter')(filter)
-#@inclusion_tag('admin/filters')
+#@register.inclusion_tag('admin/filters')
def filters(cl):
return {'cl': cl}
-filters = inclusion_tag('admin/filters')(filters)
+filters = register.inclusion_tag('admin/filters')(filters)
@@ -2,24 +2,25 @@
from django.utils.html import escape
from django.utils.text import capfirst
from django.utils.functional import curry
-from django.core.template.decorators import simple_tag, inclusion_tag
from django.contrib.admin.views.main import AdminBoundField
from django.core.meta.fields import BoundField, Field
from django.core.meta import BoundRelatedObject, TABULAR, STACKED
from django.conf.settings import ADMIN_MEDIA_PREFIX
import re
+register = template.Library()
+
word_re = re.compile('[A-Z][a-z]+')
def class_name_to_underscored(name):
return '_'.join([s.lower() for s in word_re.findall(name)[:-1]])
-#@simple_tag
+#@register.simple_tag
def include_admin_script(script_path):
return '<script type="text/javascript" src="%s%s"></script>' % (ADMIN_MEDIA_PREFIX, script_path)
-include_admin_script = simple_tag(include_admin_script)
+include_admin_script = register.simple_tag(include_admin_script)
-#@inclusion_tag('admin/submit_line', takes_context=True)
+#@register.inclusion_tag('admin/submit_line', takes_context=True)
def submit_row(context, bound_manipulator):
change = context['change']
add = context['add']
@@ -36,9 +37,9 @@ def submit_row(context, bound_manipulator):
'show_save_and_continue': not is_popup,
'show_save': True
}
-submit_row = inclusion_tag('admin/submit_line', takes_context=True)(submit_row)
+submit_row = register.inclusion_tag('admin/submit_line', takes_context=True)(submit_row)
-#@simple_tag
+#@register.simple_tag
def field_label(bound_field):
class_names = []
if isinstance(bound_field.field, meta.BooleanField):
@@ -53,7 +54,7 @@ def field_label(bound_field):
class_str = class_names and ' class="%s"' % ' '.join(class_names) or ''
return '<label for="%s"%s>%s%s</label> ' % (bound_field.element_id, class_str, \
capfirst(bound_field.field.verbose_name), colon)
-field_label = simple_tag(field_label)
+field_label = register.simple_tag(field_label)
class FieldWidgetNode(template.Node):
nodelists = {}
@@ -170,12 +171,12 @@ def render(self, context):
context.pop()
return output
-#@simple_tag
+#@register.simple_tag
def output_all(form_fields):
return ''.join([str(f) for f in form_fields])
-output_all = simple_tag(output_all)
+output_all = register.simple_tag(output_all)
-#@simple_tag
+#@register.simple_tag
def auto_populated_field_script(auto_pop_fields, change = False):
for field in auto_pop_fields:
t = []
@@ -191,9 +192,9 @@ def auto_populated_field_script(auto_pop_fields, change = False):
' if(!e._changed) { e.value = URLify(%s, %s);} }; ' % (
f, field.name, add_values, field.maxlength))
return ''.join(t)
-auto_populated_field_script = simple_tag(auto_populated_field_script)
+auto_populated_field_script = register.simple_tag(auto_populated_field_script)
-#@simple_tag
+#@register.simple_tag
def filter_interface_script_maybe(bound_field):
f = bound_field.field
if f.rel and isinstance(f.rel, meta.ManyToMany) and f.rel.filter_interface:
@@ -202,7 +203,7 @@ def filter_interface_script_maybe(bound_field):
f.name, f.verbose_name, f.rel.filter_interface-1, ADMIN_MEDIA_PREFIX)
else:
return ''
-filter_interface_script_maybe = simple_tag(filter_interface_script_maybe)
+filter_interface_script_maybe = register.simple_tag(filter_interface_script_maybe)
def do_one_arg_tag(node_factory, parser,token):
tokens = token.contents.split()
@@ -213,7 +214,7 @@ def do_one_arg_tag(node_factory, parser,token):
def register_one_arg_tag(node):
tag_name = class_name_to_underscored(node.__name__)
parse_func = curry(do_one_arg_tag, node)
- template.register_tag(tag_name, parse_func)
+ register.tag(tag_name, parse_func)
one_arg_tag_nodes = (
FieldWidgetNode,
@@ -223,7 +224,7 @@ def register_one_arg_tag(node):
for node in one_arg_tag_nodes:
register_one_arg_tag(node)
-#@inclusion_tag('admin/field_line', takes_context=True)
+#@register.inclusion_tag('admin/field_line', takes_context=True)
def admin_field_line(context, argument_val):
if (isinstance(argument_val, BoundField)):
bound_fields = [argument_val]
@@ -249,10 +250,10 @@ def admin_field_line(context, argument_val):
'bound_fields': bound_fields,
'class_names': " ".join(class_names),
}
-admin_field_line = inclusion_tag('admin/field_line', takes_context=True)(admin_field_line)
+admin_field_line = register.inclusion_tag('admin/field_line', takes_context=True)(admin_field_line)
-#@simple_tag
+#@register.simple_tag
def object_pk(bound_manip, ordered_obj):
return bound_manip.get_ordered_object_pk(ordered_obj)
-object_pk = simple_tag(object_pk)
+object_pk = register.simple_tag(object_pk)
@@ -1,5 +1,7 @@
from django.core import template
+register = template.Library()
+
class AdminApplistNode(template.Node):
def __init__(self, varname):
self.varname = varname
@@ -54,4 +56,4 @@ def get_admin_app_list(parser, token):
raise template.TemplateSyntaxError, "First argument to '%s' tag must be 'as'" % tokens[0]
return AdminApplistNode(tokens[2])
-template.register_tag('get_admin_app_list', get_admin_app_list)
+register.tag('get_admin_app_list', get_admin_app_list)
@@ -1,9 +1,10 @@
-from django.core.template.decorators import simple_tag
+from django.core.template import Library
+register = Library()
def admin_media_prefix():
try:
from django.conf.settings import ADMIN_MEDIA_PREFIX
except ImportError:
return ''
return ADMIN_MEDIA_PREFIX
-admin_media_prefix = simple_tag(admin_media_prefix)
+admin_media_prefix = register.simple_tag(admin_media_prefix)
@@ -1,6 +1,8 @@
from django.models.admin import log
from django.core import template
+register = template.Library()
+
class AdminLogNode(template.Node):
def __init__(self, limit, varname, user):
self.limit, self.varname, self.user = limit, varname, user
@@ -48,4 +50,4 @@ def __call__(self, parser, token):
raise template.TemplateSyntaxError, "Fourth argument in '%s' must be 'for_user'" % self.tag_name
return AdminLogNode(limit=tokens[1], varname=tokens[3], user=(len(tokens) > 5 and tokens[5] or None))
-template.register_tag('get_admin_log', DoGetAdminLog('get_admin_log'))
+register.tag('get_admin_log', DoGetAdminLog('get_admin_log'))
@@ -50,21 +50,23 @@ def isValidTemplate(self, field_data, all_data):
return
# so that inheritance works in the site's context, register a new function
- # for "extends" that uses the site's TEMPLATE_DIR instead
+ # for "extends" that uses the site's TEMPLATE_DIRS instead.
def new_do_extends(parser, token):
node = loader.do_extends(parser, token)
node.template_dirs = settings_module.TEMPLATE_DIRS
return node
- template.register_tag('extends', new_do_extends)
+ register = template.Library()
+ register.tag('extends', new_do_extends)
+ template.builtins.append(register)
- # now validate the template using the new template dirs
- # making sure to reset the extends function in any case
+ # Now validate the template using the new template dirs
+ # making sure to reset the extends function in any case.
error = None
try:
tmpl = loader.get_template_from_string(field_data)
tmpl.render(template.Context({}))
except template.TemplateSyntaxError, e:
error = e
- template.register_tag('extends', loader.do_extends)
+ template.builtins.remove(register)
if error:
raise validators.ValidationError, e.args
@@ -6,6 +6,8 @@
from django.models.core import contenttypes
import re
+register = template.Library()
+
COMMENT_FORM = '''
{% load i18n %}
{% if display_form %}
@@ -360,10 +362,10 @@ def __call__(self, parser, token):
return CommentListNode(package, module, var_name, obj_id, tokens[5], self.free, ordering)
# registration comments
-template.register_tag('get_comment_list', DoGetCommentList(False))
-template.register_tag('comment_form', DoCommentForm(False))
-template.register_tag('get_comment_count', DoCommentCount(False))
+register.tag('get_comment_list', DoGetCommentList(False))
+register.tag('comment_form', DoCommentForm(False))
+register.tag('get_comment_count', DoCommentCount(False))
# free comments
-template.register_tag('get_free_comment_list', DoGetCommentList(True))
-template.register_tag('free_comment_form', DoCommentForm(True))
-template.register_tag('get_free_comment_count', DoCommentCount(True))
+register.tag('get_free_comment_list', DoGetCommentList(True))
+register.tag('free_comment_form', DoCommentForm(True))
+register.tag('get_free_comment_count', DoCommentCount(True))
Oops, something went wrong. Retry.

0 comments on commit 3ede006

Please sign in to comment.