Cleaned up the django.template namespace.
Since this package is going to hold both the implementation of the Django Template Language and the infrastructure for Multiple Template Engines, it should be untied from the DTL as much as possible within our backwards-compatibility policy. Only public APIs (i.e. APIs mentioned in the documentation) were left.
This commit is contained in:
parent
bfa21ddf76
commit
7eefdbf7ab
|
@ -3,7 +3,6 @@ import inspect
|
|||
import os
|
||||
import re
|
||||
|
||||
from django import template
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
|
@ -13,6 +12,8 @@ from django.core.exceptions import ViewDoesNotExist
|
|||
from django.http import Http404
|
||||
from django.core import urlresolvers
|
||||
from django.contrib.admindocs import utils
|
||||
from django.template.base import (builtins, get_library,
|
||||
get_templatetags_modules, InvalidTemplateLibrary, libraries)
|
||||
from django.template.engine import Engine
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils._os import upath
|
||||
|
@ -61,8 +62,8 @@ class TemplateTagIndexView(BaseAdminDocsView):
|
|||
load_all_installed_template_libraries()
|
||||
|
||||
tags = []
|
||||
app_libs = list(six.iteritems(template.libraries))
|
||||
builtin_libs = [(None, lib) for lib in template.builtins]
|
||||
app_libs = list(six.iteritems(libraries))
|
||||
builtin_libs = [(None, lib) for lib in builtins]
|
||||
for module_name, library in builtin_libs + app_libs:
|
||||
for tag_name, tag_func in library.tags.items():
|
||||
title, body, metadata = utils.parse_docstring(tag_func.__doc__)
|
||||
|
@ -72,7 +73,7 @@ class TemplateTagIndexView(BaseAdminDocsView):
|
|||
body = utils.parse_rst(body, 'tag', _('tag:') + tag_name)
|
||||
for key in metadata:
|
||||
metadata[key] = utils.parse_rst(metadata[key], 'tag', _('tag:') + tag_name)
|
||||
if library in template.builtins:
|
||||
if library in builtins:
|
||||
tag_library = ''
|
||||
else:
|
||||
tag_library = module_name.split('.')[-1]
|
||||
|
@ -94,8 +95,8 @@ class TemplateFilterIndexView(BaseAdminDocsView):
|
|||
load_all_installed_template_libraries()
|
||||
|
||||
filters = []
|
||||
app_libs = list(six.iteritems(template.libraries))
|
||||
builtin_libs = [(None, lib) for lib in template.builtins]
|
||||
app_libs = list(six.iteritems(libraries))
|
||||
builtin_libs = [(None, lib) for lib in builtins]
|
||||
for module_name, library in builtin_libs + app_libs:
|
||||
for filter_name, filter_func in library.filters.items():
|
||||
title, body, metadata = utils.parse_docstring(filter_func.__doc__)
|
||||
|
@ -105,7 +106,7 @@ class TemplateFilterIndexView(BaseAdminDocsView):
|
|||
body = utils.parse_rst(body, 'filter', _('filter:') + filter_name)
|
||||
for key in metadata:
|
||||
metadata[key] = utils.parse_rst(metadata[key], 'filter', _('filter:') + filter_name)
|
||||
if library in template.builtins:
|
||||
if library in builtins:
|
||||
tag_library = ''
|
||||
else:
|
||||
tag_library = module_name.split('.')[-1]
|
||||
|
@ -313,7 +314,7 @@ class TemplateDetailView(BaseAdminDocsView):
|
|||
|
||||
def load_all_installed_template_libraries():
|
||||
# Load/register all template tag libraries from installed apps.
|
||||
for module_name in template.get_templatetags_modules():
|
||||
for module_name in get_templatetags_modules():
|
||||
mod = import_module(module_name)
|
||||
if not hasattr(mod, '__file__'):
|
||||
# e.g. packages installed as eggs
|
||||
|
@ -330,8 +331,8 @@ def load_all_installed_template_libraries():
|
|||
else:
|
||||
for library_name in libraries:
|
||||
try:
|
||||
template.get_library(library_name)
|
||||
except template.InvalidTemplateLibrary:
|
||||
get_library(library_name)
|
||||
except InvalidTemplateLibrary:
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -1,80 +1,17 @@
|
|||
"""
|
||||
This is the Django template system.
|
||||
|
||||
How it works:
|
||||
|
||||
The Lexer.tokenize() function converts a template string (i.e., a string containing
|
||||
markup with custom template tags) to tokens, which can be either plain text
|
||||
(TOKEN_TEXT), variables (TOKEN_VAR) or block statements (TOKEN_BLOCK).
|
||||
|
||||
The Parser() class takes a list of tokens in its constructor, and its parse()
|
||||
method returns a compiled template -- which is, under the hood, a list of
|
||||
Node objects.
|
||||
|
||||
Each Node is responsible for creating some sort of output -- e.g. simple text
|
||||
(TextNode), variable values in a given context (VariableNode), results of basic
|
||||
logic (IfNode), results of looping (ForNode), or anything else. The core Node
|
||||
types are TextNode, VariableNode, IfNode and ForNode, but plugin modules can
|
||||
define their own custom node types.
|
||||
|
||||
Each Node has a render() method, which takes a Context and returns a string of
|
||||
the rendered node. For example, the render() method of a Variable Node returns
|
||||
the variable's value as a string. The render() method of a ForNode returns the
|
||||
rendered output of whatever was inside the loop, recursively.
|
||||
|
||||
The Template class is a convenient wrapper that takes care of template
|
||||
compilation and rendering.
|
||||
|
||||
Usage:
|
||||
|
||||
The only thing you should ever use directly in this file is the Template class.
|
||||
Create a compiled template object with a template_string, then call render()
|
||||
with a context. In the compilation stage, the TemplateSyntaxError exception
|
||||
will be raised if the template doesn't have proper syntax.
|
||||
|
||||
Sample code:
|
||||
|
||||
>>> from django import template
|
||||
>>> s = u'<html>{% if test %}<h1>{{ varvalue }}</h1>{% endif %}</html>'
|
||||
>>> t = template.Template(s)
|
||||
|
||||
(t is now a compiled template, and its render() method can be called multiple
|
||||
times with multiple contexts)
|
||||
|
||||
>>> c = template.Context({'test':True, 'varvalue': 'Hello'})
|
||||
>>> t.render(c)
|
||||
u'<html><h1>Hello</h1></html>'
|
||||
>>> c = template.Context({'test':False, 'varvalue': 'Hello'})
|
||||
>>> t.render(c)
|
||||
u'<html></html>'
|
||||
"""
|
||||
|
||||
# Template lexing symbols
|
||||
from django.template.base import (ALLOWED_VARIABLE_CHARS, BLOCK_TAG_END, # NOQA
|
||||
BLOCK_TAG_START, COMMENT_TAG_END, COMMENT_TAG_START,
|
||||
FILTER_ARGUMENT_SEPARATOR, FILTER_SEPARATOR, SINGLE_BRACE_END,
|
||||
SINGLE_BRACE_START, TOKEN_BLOCK, TOKEN_COMMENT, TOKEN_TEXT, TOKEN_VAR,
|
||||
TRANSLATOR_COMMENT_MARK, UNKNOWN_SOURCE, VARIABLE_ATTRIBUTE_SEPARATOR,
|
||||
VARIABLE_TAG_END, VARIABLE_TAG_START, filter_re, tag_re)
|
||||
|
||||
# Exceptions
|
||||
from django.template.base import (ContextPopException, InvalidTemplateLibrary, # NOQA
|
||||
TemplateDoesNotExist, TemplateEncodingError, TemplateSyntaxError,
|
||||
VariableDoesNotExist)
|
||||
# Public exceptions
|
||||
from .base import (TemplateDoesNotExist, TemplateSyntaxError, # NOQA
|
||||
VariableDoesNotExist)
|
||||
from .context import ContextPopException # NOQA
|
||||
|
||||
# Template parts
|
||||
from django.template.base import (Context, FilterExpression, Lexer, Node, # NOQA
|
||||
NodeList, Parser, RequestContext, Origin, StringOrigin, Template,
|
||||
TextNode, Token, TokenParser, Variable, VariableNode, constant_string,
|
||||
filter_raw_string)
|
||||
from .base import (Context, Node, NodeList, RequestContext, # NOQA
|
||||
StringOrigin, Template, Variable)
|
||||
|
||||
# Compiling templates
|
||||
from django.template.base import (resolve_variable, # NOQA
|
||||
unescape_string_literal, generic_tag_compiler)
|
||||
# Deprecated in Django 1.8, will be removed in Django 2.0.
|
||||
from .base import resolve_variable # NOQA
|
||||
|
||||
# Library management
|
||||
from django.template.base import (Library, add_to_builtins, builtins, # NOQA
|
||||
get_library, get_templatetags_modules, get_text_list, import_library,
|
||||
libraries)
|
||||
from .base import Library # NOQA
|
||||
|
||||
|
||||
__all__ = ('Template', 'Context', 'RequestContext')
|
||||
|
|
|
@ -1,3 +1,54 @@
|
|||
"""
|
||||
This is the Django template system.
|
||||
|
||||
How it works:
|
||||
|
||||
The Lexer.tokenize() function converts a template string (i.e., a string containing
|
||||
markup with custom template tags) to tokens, which can be either plain text
|
||||
(TOKEN_TEXT), variables (TOKEN_VAR) or block statements (TOKEN_BLOCK).
|
||||
|
||||
The Parser() class takes a list of tokens in its constructor, and its parse()
|
||||
method returns a compiled template -- which is, under the hood, a list of
|
||||
Node objects.
|
||||
|
||||
Each Node is responsible for creating some sort of output -- e.g. simple text
|
||||
(TextNode), variable values in a given context (VariableNode), results of basic
|
||||
logic (IfNode), results of looping (ForNode), or anything else. The core Node
|
||||
types are TextNode, VariableNode, IfNode and ForNode, but plugin modules can
|
||||
define their own custom node types.
|
||||
|
||||
Each Node has a render() method, which takes a Context and returns a string of
|
||||
the rendered node. For example, the render() method of a Variable Node returns
|
||||
the variable's value as a string. The render() method of a ForNode returns the
|
||||
rendered output of whatever was inside the loop, recursively.
|
||||
|
||||
The Template class is a convenient wrapper that takes care of template
|
||||
compilation and rendering.
|
||||
|
||||
Usage:
|
||||
|
||||
The only thing you should ever use directly in this file is the Template class.
|
||||
Create a compiled template object with a template_string, then call render()
|
||||
with a context. In the compilation stage, the TemplateSyntaxError exception
|
||||
will be raised if the template doesn't have proper syntax.
|
||||
|
||||
Sample code:
|
||||
|
||||
>>> from django import template
|
||||
>>> s = u'<html>{% if test %}<h1>{{ varvalue }}</h1>{% endif %}</html>'
|
||||
>>> t = template.Template(s)
|
||||
|
||||
(t is now a compiled template, and its render() method can be called multiple
|
||||
times with multiple contexts)
|
||||
|
||||
>>> c = template.Context({'test':True, 'varvalue': 'Hello'})
|
||||
>>> t.render(c)
|
||||
u'<html><h1>Hello</h1></html>'
|
||||
>>> c = template.Context({'test':False, 'varvalue': 'Hello'})
|
||||
>>> t.render(c)
|
||||
u'<html></html>'
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import re
|
||||
|
|
|
@ -3,9 +3,8 @@ import re
|
|||
import sys
|
||||
|
||||
from django.conf import settings
|
||||
from django.template import (Node, Variable, TemplateSyntaxError,
|
||||
TokenParser, Library, TOKEN_TEXT, TOKEN_VAR)
|
||||
from django.template.base import render_value_in_context
|
||||
from django.template import Library, Node, TemplateSyntaxError, Variable
|
||||
from django.template.base import render_value_in_context, TokenParser, TOKEN_TEXT, TOKEN_VAR
|
||||
from django.template.defaulttags import token_kwargs
|
||||
from django.utils import six
|
||||
from django.utils import translation
|
||||
|
|
|
@ -544,8 +544,8 @@ def templatize(src, origin=None):
|
|||
does so by translating the Django translation tags into standard gettext
|
||||
function invocations.
|
||||
"""
|
||||
from django.template import (Lexer, TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK,
|
||||
TOKEN_COMMENT, TRANSLATOR_COMMENT_MARK)
|
||||
from django.template.base import (Lexer, TOKEN_TEXT, TOKEN_VAR,
|
||||
TOKEN_BLOCK, TOKEN_COMMENT, TRANSLATOR_COMMENT_MARK)
|
||||
src = force_text(src, settings.FILE_CHARSET)
|
||||
out = StringIO('')
|
||||
message_context = None
|
||||
|
|
|
@ -832,6 +832,14 @@ Django previously closed database connections between each test within a
|
|||
``TestCase`` within a transaction. If some of your tests relied on the old
|
||||
behavior, you should have them inherit from ``TransactionTestCase`` instead.
|
||||
|
||||
Cleanup of the ``django.template`` namespace
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you've been relying on private APIs exposed in the ``django.template``
|
||||
module, you may have to import them from ``django.template.base`` instead.
|
||||
|
||||
Also ``django.template.base.compile_string()`` was removed.
|
||||
|
||||
Miscellaneous
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
@ -906,8 +914,6 @@ Miscellaneous
|
|||
delete a key if ``set()`` fails. This is necessary to ensure the ``cache_db``
|
||||
session store always fetches the most current session data.
|
||||
|
||||
* Private API ``django.template.compile_string`` was removed.
|
||||
|
||||
* Private APIs ``override_template_loaders`` and ``override_with_test_loader``
|
||||
in ``django.test.utils`` were removed. Override ``TEMPLATE_LOADERS`` with
|
||||
``override_settings`` instead.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from unittest import TestCase
|
||||
|
||||
from django.template import Context, Template, VariableNode
|
||||
from django.template import Context, Template
|
||||
from django.template.base import VariableNode
|
||||
from django.test import override_settings
|
||||
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ from __future__ import unicode_literals
|
|||
|
||||
from unittest import TestCase
|
||||
|
||||
from django.template import (TokenParser, FilterExpression, Parser, Variable,
|
||||
Template, TemplateSyntaxError, Library)
|
||||
from django.template import Library, Template, TemplateSyntaxError
|
||||
from django.template.base import FilterExpression, Parser, TokenParser, Variable
|
||||
from django.test import override_settings
|
||||
from django.utils import six
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ from __future__ import unicode_literals
|
|||
|
||||
from unittest import TestCase
|
||||
|
||||
from django.template import Template, TemplateEncodingError, Context
|
||||
from django.template import Template, Context
|
||||
from django.template.base import TemplateEncodingError
|
||||
from django.utils.safestring import SafeData
|
||||
from django.utils import six
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ import unittest
|
|||
from django import template
|
||||
from django.contrib.auth.models import Group
|
||||
from django.core import urlresolvers
|
||||
from django.template import loader, Context, RequestContext, Template, TemplateSyntaxError
|
||||
from django.template import (base as template_base, loader,
|
||||
Context, RequestContext, Template, TemplateSyntaxError)
|
||||
from django.template.engine import Engine
|
||||
from django.template.loaders import app_directories, filesystem
|
||||
from django.test import RequestFactory, SimpleTestCase
|
||||
|
@ -245,7 +246,7 @@ class TemplateRegressionTests(SimpleTestCase):
|
|||
|
||||
def test_token_smart_split(self):
|
||||
# Regression test for #7027
|
||||
token = template.Token(template.TOKEN_BLOCK, 'sometag _("Page not found") value|yesno:_("yes,no")')
|
||||
token = template_base.Token(template_base.TOKEN_BLOCK, 'sometag _("Page not found") value|yesno:_("yes,no")')
|
||||
split = token.split_contents()
|
||||
self.assertEqual(split, ["sometag", '_("Page not found")', 'value|yesno:_("yes,no")'])
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import functools
|
|||
|
||||
from django import template
|
||||
from django.template import Library
|
||||
from django.template.base import Context
|
||||
from django.template.base import Context, libraries
|
||||
from django.template.engine import Engine
|
||||
from django.template.loader import get_template
|
||||
from django.test.utils import override_settings
|
||||
|
@ -100,9 +100,11 @@ def upper(value):
|
|||
def register_test_tags(func):
|
||||
@functools.wraps(func)
|
||||
def inner(self):
|
||||
template.libraries['testtags'] = register
|
||||
func(self)
|
||||
del template.libraries['testtags']
|
||||
libraries['testtags'] = register
|
||||
try:
|
||||
func(self)
|
||||
finally:
|
||||
del libraries['testtags']
|
||||
return inner
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue