Skip to main content

将模板升级到Django 1.8

Django模板系统在Django 1.8中进行了大修,当它获得了对多个模板引擎的支持。本文档补充了 发行说明 的一些主题的详细升级说明。

TEMPLATES 设置

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

如果您的设置模块定义了 ALLOWED_INCLUDE_ROOTSTEMPLATE_STRING_IF_INVALID,请将其值包含在 'OPTIONS' 字典中的 'allowed_include_roots''string_if_invalid' 键下。

如果它将 TEMPLATE_DEBUG 设置为与 DEBUG 不同的值,则将该值包括在 'OPTIONS' 中的 'debug' 密钥下。

一旦定义了 TEMPLATES,您可以安全地删除 ALLOWED_INCLUDE_ROOTSTEMPLATE_CONTEXT_PROCESSORSTEMPLATE_DEBUGTEMPLATE_DIRSTEMPLATE_LOADERSTEMPLATE_STRING_IF_INVALID

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

django.template.loader

get_template()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 1.10中支持。

如果在使用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 后端时,它仍然有效,但可插入应用程序无法控制此要求。

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