diff --git a/docs/ref/templates/index.txt b/docs/ref/templates/index.txt index efc97494ae..e5730488c1 100644 --- a/docs/ref/templates/index.txt +++ b/docs/ref/templates/index.txt @@ -14,6 +14,7 @@ material, see :doc:`/topics/templates` topic guide. language builtins api + upgrading .. seealso:: diff --git a/docs/ref/templates/upgrading.txt b/docs/ref/templates/upgrading.txt new file mode 100644 index 0000000000..b592cd9f86 --- /dev/null +++ b/docs/ref/templates/upgrading.txt @@ -0,0 +1,187 @@ +================================= +Upgrading templates to Django 1.8 +================================= + +Django's template system was overhauled in Django 1.8 when it gained support +for multiple template engines. This document complements the :doc:`release +notes ` with detailed upgrade instructions on some topics. + +The :setting:`TEMPLATES` settings +================================= + +A new setting was introduced in Django 1.8: :setting:`TEMPLATES`. All existing +template-related settings except :setting:`TEMPLATE_DEBUG` were deprecated. + +During the deprecation period, Django will create a backwards-compatible +:setting:`TEMPLATES` based on the ``TEMPLATE_*`` settings if you don't define +it yourself. + +Here's how to define :setting:`TEMPLATES` in your settings module. + +If you're using the default value of ``TEMPLATE_LOADERS``, that is, if it +isn't defined in your settings file or if it's set to:: + + ('django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader') + +then you should define :setting:`TEMPLATES` as follows:: + + TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + # insert your TEMPLATE_DIRS here + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + # Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this + # list if you haven't customized them: + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.debug', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, + ] + +If you aren't using the default value of ``TEMPLATE_LOADERS``, then you should +define :setting:`TEMPLATES` as follows:: + + TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + # insert your TEMPLATE_DIRS here + ], + 'OPTIONS': { + 'context_processors': [ + # Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this + # list if you haven't customized them: + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.debug', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + ], + 'loaders': [ + # insert your TEMPLATE_LOADERS here + ] + }, + }, + ] + +Furthermore you should replace ``django.core.context_processors`` with +``django.template.context_processors`` in the names of context processors. + +If your settings module defines ``ALLOWED_INCLUDE_ROOTS`` or +``TEMPLATE_STRING_IF_INVALID``, include their values under the +``'allowed_include_roots'`` and ``'string_if_invalid'`` keys in the +``'OPTIONS'`` dictionary. + +Once you have defined :setting:`TEMPLATES`, you can safely remove +``ALLOWED_INCLUDE_ROOTS``, ``TEMPLATE_CONTEXT_PROCESSORS``, ``TEMPLATE_DIRS``, +``TEMPLATE_LOADERS``, and ``TEMPLATE_STRING_IF_INVALID``. + +If you are overriding some of these settings in tests, you should override the +entire :setting:`TEMPLATES` setting instead. + +:mod:`django.template.loader` +============================= + +:func:`~django.template.loader.get_template` and :func:`~django.template.loader.select_template` +------------------------------------------------------------------------------------------------ + +In Django 1.8 :func:`~django.template.loader.get_template` and +:func:`~django.template.loader.select_template` returns a backend-dependent +``Template`` instead of a :class:`django.template.Template`. + +``Template`` objects must provide a +:meth:`~django.template.backends.base.Template.render` method whose signature +differs slightly from the Django template language's +:meth:`~django.template.Template.render`. + +Instead of:: + + from django.template import Context + from django.template.loader import get_template + + template = get_template('hello.html') + html = template.render(Context({'name': 'world'})) + +You should write:: + + from django.template.loader import get_template + + template = get_template('hello.html') + html = template.render({'name': 'world'}) + +And instead of:: + + from django.template import RequestContext + from django.template.loader import get_template + + template = get_template('hello.html') + html = template.render(RequestContext(request, {'name': 'world'})) + +You should write:: + + from django.template.loader import get_template + + template = get_template('hello.html') + html = template.render({'name': 'world'}, request) + +Passing a :class:`~django.template.Context` or a +:class:`~django.template.RequestContext` is still possible when the template +is loaded by a :class:`~django.template.backends.django.DjangoTemplates` +backend but it's deprecated and won't be supported in Django 2.0. + +If you're loading a template while you're rendering another template with the +Django template language and you have access to the current context, for +instance in the ``render()`` method of a template tag, you can use the current +:class:`~django.template.Engine` directly. Instead of:: + + + from django.template.loader import get_template + template = get_template('included.html') + +You can write:: + + template = context.engine.get_template('included.html') + +This will load the template with the current engine without triggering the +multiple template engines machinery, which is usually the desired behavior. + +``get_template_from_string()`` +------------------------------ + +Private API ``get_template_from_string(template_code)`` was removed in Django +1.8 because it had no way to choose an engine to compile the template. There +are two solutions to replace it. + +You can use a template engine's ``from_string()`` method:: + + from django.template import engines + + template = engines['django'].from_string(template_code) + +Or you can use the same trick as above, if you have access to the current +context:: + + template = context.engine.from_string(template_code) + +Or you can instantiate a :class:`~django.template.Template` directly:: + + from django.template import Template + + template = Template(template_code) + +The last solution requires that :setting:`TEMPLATES` defines exactly one +:class:`~django.template.backends.django.DjangoTemplates` backend. That engine +will automatically be used to render the template. diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index 7b01fbf9fe..dde70c9f84 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -45,6 +45,17 @@ new official API have been deprecated and will eventually be removed. A :ref:`guide to migrating from the old API to the new API ` has been provided. +Multiple template engines +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Django 1.8 defines a stable API for integrating template backends. It includes +built-in support for the Django template language and for Jinja2_. It supports +rendering templates with multiple engines within the same project. Learn more +about the new features in the :doc:`topic guide ` and check +the :doc:`upgrade instructions ` for details. + +.. _Jinja2: http://jinja.pocoo.org/ + Security enhancements ~~~~~~~~~~~~~~~~~~~~~