Upgrading templates to Django 1.8

当Django 1.8获得对多个模板引擎的支持时,Django的模板系统被大修。本文档补充了release notes以及有关某些主题的详细升级说明。

The TEMPLATES settings

Django 1.8中引入了一项新设置:TEMPLATES所有现有的模板相关设置已弃用。

在弃用期间,如果您不自行定义,Django将根据TEMPLATE_*设置创建向后兼容的TEMPLATES

以下说明如何在设置模块中定义TEMPLATES

如果您使用的默认值为TEMPLATE_LOADERS,也就是说,如果未在设置文件中定义或设置为:

('django.template.loaders.filesystem.Loader',
 'django.template.loaders.app_directories.Loader')

则应定义TEMPLATES,如下所示:

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',
            ],
        },
    },
]

如果您未使用默认值TEMPLATE_LOADERS,则应定义TEMPLATES,如下所示:

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
            ]
        },
    },
]

此外,您应该在上下文处理器的名称中将django.core.context_processors替换为django.template.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.

If it sets TEMPLATE_DEBUG to a value that differs from DEBUG, include that value under the 'debug' key in 'OPTIONS'.

Once you have defined TEMPLATES, you can safely remove ALLOWED_INCLUDE_ROOTS, TEMPLATE_CONTEXT_PROCESSORS, TEMPLATE_DEBUG, TEMPLATE_DIRS, TEMPLATE_LOADERS, and TEMPLATE_STRING_IF_INVALID.

如果您在测试中覆写某些设置,则应改为覆盖整个TEMPLATES设置。

django.template.loader

get_template() and select_template()

在Django 1.8 get_template()select_template()返回一个后端依赖的Template,而不是django.template.Template

例如,如果get_template()加载了具有DjangoTemplates后端的模板,则会返回django.template.backends.django.Template

Template对象必须提供render()方法,其签名与Django模板语言的render()稍有不同。

代替:

from django.template import Context
from django.template.loader import get_template

template = get_template('hello.html')
html = template.render(Context({'name': 'world'}))

你应该写:

from django.template.loader import get_template

template = get_template('hello.html')
html = template.render({'name': 'world'})

而不是:

from django.template import RequestContext
from django.template.loader import get_template

template = get_template('hello.html')
html = template.render(RequestContext(request, {'name': 'world'}))

你应该写:

from django.template.loader import get_template

template = get_template('hello.html')
html = template.render({'name': 'world'}, request)

当模板由DjangoTemplates后端加载时,仍然可以传递ContextRequestContext,但它已被弃用,并且不会在Django中支持2.0。

如果您在使用Django模板语言呈现另一个模板并且可以访问当前上下文(例如在模板标记的render()方法中)时加载模板,则可以直接使用当前Engine代替:

from django.template.loader import get_template
template = get_template('included.html')

你可以写:

template = context.template.engine.get_template('included.html')

这将加载模板与当前引擎,而不触发多个模板引擎机械,这通常是所需的行为。与以前的解决方案不同,这会返回一个django.template.Template,如get_template(),用于Django 1.7和更早版本,避免所有向后兼容性问题。

get_template_from_string()

私人API get_template_from_string(template_code)在Django 1.8中被删除,因为它没有办法选择引擎来编译模板。

有三种选择。

如果您控制项目的设置,您可以使用配置的引擎之一:

from django.template import engines

template = engines['django'].from_string(template_code)

这会返回依赖于后端的Template对象。

对于不需要上下文处理器或其他任何事情的琐碎模板,您可以创建一个裸机引擎并使用from_string()方法:

from django.template import Engine

template = Engine().from_string(template_code)

这会返回django.template.Template,因为Engine是Django模板语言的API的一部分。这里不涉及多个模板引擎机械。

最后,如果您可以访问当前上下文,您可以使用与上述相同的技巧:

template = context.template.engine.from_string(template_code)

Template()

在较小程度上,使用Template(template_code)实例化模板遇到与get_template_from_string()相同的问题。

TEMPLATES设置仅定义一个DjangoTemplates后端时,它仍然有效,但可插拔应用程序无法控制此要求。

在这种情况下,建议在上一节中描述的最后两个解决方案。