Django模板语言:适用于Python程序员

本文档从技术角度解释了Django模板系统 - 它是如何工作的以及如何扩展它。 如果您只是在查找语言语法的参考,请参阅The Django template language

它假定了解模板,上下文,变量,标记和呈现。 如果您不熟悉这些概念,请从introduction to the Django template language开始。

概述¶ T0>

在Python中使用模板系统是一个三步过程:

  1. 您配置Engine
  2. 您将模板代码编译到Template中。
  3. 您使用Context呈现模板。

Django projects generally rely on the high level, backend agnostic APIs for each of these steps instead of the template system’s lower level APIs:

  1. 对于TEMPLATES设置中的每个DjangoTemplates后端,Django实例化一个Engine DjangoTemplates wraps Engine and adapts it to the common template backend API.
  2. django.template.loader模块提供用于加载模板的函数,例如get_template() 它们返回包含实际的django.template.Templatedjango.template.backends.django.Template
  3. The Template obtained in the previous step has a render() method which marshals a context and possibly a request into a Context and delegates the rendering to the underlying Template.

配置引擎

如果您只是使用DjangoTemplates后端,这可能不是您正在寻找的文档。 下面描述的Engine类的实例可以使用该后端的engine属性进行访问,并且下面提到的任何属性默认值都被DjangoTemplates

Enginedirs = Noneapp_dirs = Falsecontext_processors = Nonedebug = False ,loaders = Nonestring_if_invalid =''file_charset ='utf-8'libraries = None t8 >,builtins = Noneautoescape = True[source]

当实例化一个Engine时,所有参数都必须作为关键字参数传递:

  • dirs is a list of directories where the engine should look for template source files. 它用于配置filesystem.Loader

    它默认为一个空的列表。

  • app_dirs只影响loaders的默认值。 见下文。

    它默认为False

  • autoescape控制是否启用HTML自动转义。

    它默认为True

    警告

    如果您要呈现非HTML模板,请将其设置为False

  • context_processors是一个点状Python路径列表,当用模板呈现一个请求时,可用于填充上下文。 这些可调用对象将请求对象作为参数,并返回要合并到上下文中的dict个项目。

    它默认为一个空的列表。

    请参阅RequestContext了解更多信息。

  • debug is a boolean that turns on/off template debug mode. 如果它是True,模板引擎将存储额外的调试信息,这些信息可用于显示模板呈现过程中引发的任何异常的详细报告。

    它默认为False

  • loaders是模板加载器类的列表,指定为字符串。 每个Loader类都知道如何从特定源文件导入模板。 可选地,可以使用元组而不是字符串。 元组中的第一项应该是Loader类的名称,后续的项目在初始化期间传递给Loader

    它默认为一个包含以下内容的列表:

    • 'django.template.loaders.filesystem.Loader'
    • 'django.template.loaders.app_directories.Loader'当且仅当app_dirsTrue

    如果debugFalse,则这些加载器被封装在django.template.loaders.cached.Loader中。

    有关详细信息,请参见Loader types

    在Django 1.11中更改:

    debugFalse时启用缓存的模板加载器已添加。

  • string_if_invalid是字符串输出,模板系统应该使用无效(例如拼写错误)的变量。

    它默认为空字符串。

    有关详细信息,请参阅How invalid variables are handled

  • file_charset is the charset used to read template files on disk.

    它默认为'utf-8'

  • 'libraries':模板标签模块的标签和点状Python路径字典,用于注册模板引擎。 这用于添加新库或为现有库提供替代标签。 例如:

    Engine(
        libraries={
            'myapp_tags': 'path.to.myapp.tags',
            'admin.urls': 'django.contrib.admin.templatetags.admin_urls',
        },
    )
    

    可以通过将相应的字典键传递给{% load %}标签来加载库。

  • 'builtins':要添加到built-ins的模板标记模块的虚线Python路径列表。 例如:

    Engine(
        builtins=['myapp.builtins'],
    )
    

    标签和内置库中的过滤器不需要先调用{% load %}标签即可使用。

静态的 发动机。get_default()[source]

从第一个配置的DjangoTemplates引擎返回底层的Engine 如果没有引擎配置,引发ImproperlyConfigured

保留依赖于全局可用,隐式配置的引擎的API是必需的。 任何其他用途强烈不鼓励。

在Django 2.0中更改:

在旧版本中,如果配置了多个引擎而不是返回第一个引擎,则引发ImproperlyConfigured

发动机。from_string(template_code)[source]

编译给定的模板代码并返回一个Template对象。

发动机。get_template(template_name)[source]

加载具有给定名称的模板,编译它并返回一个Template对象。

发动机。select_template(template_name_list)[source]

get_template()一样,除了它需要一个名称列表并返回找到的第一个模板。

加载模板

The recommended way to create a Template is by calling the factory methods of the Engine: get_template(), select_template() and from_string().

TEMPLATES设置定义DjangoTemplates引擎的Django项目中,可以直接实例化Template 如果定义了多个DjangoTemplates引擎,则会使用第一个引擎。

Template[source]

这个类位于django.template.Template 构造函数接受一个参数 - 原始模板代码:

from django.template import Template

template = Template("My name is {{ my_name }}.")

在幕后

当您创建Template对象时,系统只解析一次您的原始模板代码。 从那时起,它就被存储在内部,作为一个树形结构来提高性能。

即使解析本身也是相当快的。 大部分的解析是通过一个单一的,简短的正则表达式来调用的。

渲染上下文

一旦你有了一个编译的Template对象,你可以用它来渲染一个上下文。 您可以重复使用相同的模板,使用不同的上下文多次渲染它。

Context(dict_=None)[source]

django.template.Context的构造函数接受一个可选的参数 - 一个将变量名称映射到变量值的字典。

有关详细信息,请参阅下面的Playing with Context objects

模板。render(context)[source]

Context调用Template对象的render()方法来“填充”模板:

>>> from django.template import Context, Template
>>> template = Template("My name is {{ my_name }}.")

>>> context = Context({"my_name": "Adrian"})
>>> template.render(context)
"My name is Adrian."

>>> context = Context({"my_name": "Dolores"})
>>> template.render(context)
"My name is Dolores."

变量和查找

变量名称必须包含任何字母(A-Z),任何数字(0-9),下划线(但不能以下划线开头)或点。

点在模板渲染中有特殊的意义。 变量名称中的点表示查找 具体而言,当模板系统在变量名称中遇到一个点时,将按以下顺序尝试以下查找:

  • 字典查找。 例如:foo["bar"]
  • 属性查找。 例如:foo.bar
  • 列表索引查找。 例如:foo[bar]

请注意,像{{ foo.bar }}这样的模板表达式中的“bar”将被解释为如果在模板上下文中存在,则不使用变量“bar”的值。

模板系统使用第一个可用的查找类型。 这是短路逻辑。 这里有一些例子:

>>> from django.template import Context, Template
>>> t = Template("My name is {{ person.first_name }}.")
>>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}}
>>> t.render(Context(d))
"My name is Joe."

>>> class PersonClass: pass
>>> p = PersonClass()
>>> p.first_name = "Ron"
>>> p.last_name = "Nasty"
>>> t.render(Context({"person": p}))
"My name is Ron."

>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
>>> t.render(c)
"The first stooge in the list is Larry."

如果变量的任何部分是可调用的,模板系统将尝试调用它。 例:

>>> class PersonClass2:
...     def name(self):
...         return "Samantha"
>>> t = Template("My name is {{ person.name }}.")
>>> t.render(Context({"person": PersonClass2}))
"My name is Samantha."

可调用变量比仅需要直接查找的变量稍微复杂一点。 这里有一些事情要记住:

  • 如果变量在调用时引发异常,则异常将被传播,除非异常具有True的属性silent_variable_failure If the exception does have a silent_variable_failure attribute whose value is True, the variable will render as the value of the engine’s string_if_invalid configuration option (an empty string, by default). 例:

    >>> t = Template("My name is {{ person.first_name }}.")
    >>> class PersonClass3:
    ...     def first_name(self):
    ...         raise AssertionError("foo")
    >>> p = PersonClass3()
    >>> t.render(Context({"person": p}))
    Traceback (most recent call last):
    ...
    AssertionError: foo
    
    >>> class SilentAssertionError(Exception):
    ...     silent_variable_failure = True
    >>> class PersonClass4:
    ...     def first_name(self):
    ...         raise SilentAssertionError
    >>> p = PersonClass4()
    >>> t.render(Context({"person": p}))
    "My name is ."
    

    Note that django.core.exceptions.ObjectDoesNotExist, which is the base class for all Django database API DoesNotExist exceptions, has silent_variable_failure = True. 因此,如果您将Django模板与Django模型对象一起使用,则任何DoesNotExist异常都将自动失败。

  • 只有在没有必要参数的情况下才能调用变量。 否则,系统将返回引擎的string_if_invalid选项的值。

  • 显然,调用某些变量时可能会有副作用,这可能是愚蠢的,也可能是一个安全漏洞,允许模板系统访问它们。

    每个Django模型对象上的delete()方法就是一个很好的例子。 模板系统不应该被允许做这样的事情:

    I will now delete this valuable data. {{ data.delete }}
    

    为了防止这种情况,请在可调用变量上设置一个alters_data属性。 如果模板系统设置了alters_data=True,模板系统将不会调用变量,而是无条件地用string_if_invalid替换变量。 The dynamically-generated delete() and save() methods on Django model objects get alters_data=True automatically. 例:

    def sensitive_function(self):
        self.database_record.delete()
    sensitive_function.alters_data = True
    
  • 有时您可能想要关闭此功能出于其他原因,并告诉模板系统留下一个变量,不管什么,不要。 为此,请在值为True的可调用对象上设置do_not_call_in_templates属性。 那么模板系统将会像您的变量不可调用一样(例如,允许您访问可调用的属性)。

如何处理无效的变量

一般情况下,如果一个变量不存在,模板系统会默认插入引擎的string_if_invalid配置选项,该选项默认设置为''(空字符串) 。

只有当string_if_invalid设置为''(空字符串)时,才会应用应用于无效变量的过滤器。 如果string_if_invalid被设置为任何其他值,则可变过滤器将被忽略。

This behavior is slightly different for the if, for and regroup template tags. 如果为这些模板标签中的一个提供了无效变量,则该变量将被解释为None 过滤器总是应用于这些模板标签中的无效变量。

如果string_if_invalid包含'%s',则格式标记将替换为无效变量的名称。

仅用于调试目的!

虽然string_if_invalid可以成为一个有用的调试工具,但将其作为“开发默认”打开是个不错的主意。

当遇到不存在的变量时,许多模板(包括管理站点中的模板)都依赖于模板系统的静默。 如果将''以外的值分配给string_if_invalid,则会遇到这些模板和网站的渲染问题。

通常情况下,只应该启用string_if_invalid才能调试特定的模板问题,然后在调试完成后清除。

内置变量

每个上下文都包含TrueFalseNone 正如您所期望的那样,这些变量将解析为相应的Python对象。

字符串文字限制

Django的模板语言无法逃避用于自己语法的字符。 例如,如果您需要输出像{%%}这样的字符序列,则需要templatetag标记。

如果要将这些序列包含在模板过滤器或标记参数中,则存在类似的问题。 例如,在解析块标记时,Django的模板解析器会在{%之后查找第一个出现的%} 这可以防止使用"%}"作为字符串文字。 例如,下面的表达式会产生TemplateSyntaxError

{% include "template.html" tvar="Some string literal with %} in it." %}

{% with tvar="Some string literal with %} in it." %}{% endwith %}

通过在过滤器参数中使用保留序列,可以触发相同的问题:

{{ some.variable|default:"}}" }}

如果您需要对这些序列使用字符串,请将其存储在模板变量中,或使用自定义模板标记或过滤器来解决该限制。

使用Context对象播放

Most of the time, you’ll instantiate Context objects by passing in a fully-populated dictionary to Context(). 但是,在使用标准字典语法实例化之后,您可以从Context对象添加和删除项目:

>>> from django.template import Context
>>> c = Context({"foo": "bar"})
>>> c['foo']
'bar'
>>> del c['foo']
>>> c['foo']
Traceback (most recent call last):
...
KeyError: 'foo'
>>> c['newvariable'] = 'hello'
>>> c['newvariable']
'hello'
语境。getkeyotherwise = None

如果key在上下文中,则返回key的值,否则返回otherwise

语境。setdefaultkeydefault = None

如果key在上下文中,则返回其值。 否则,将key插入default,并返回default

语境。弹出 T0>()¶ T1>
语境。推 T0>()¶ T1>
例外 ContextPopException[source]

一个Context对象是一个堆栈。 也就是说,你可以push()pop()它。 如果pop()太多,会引发django.template.ContextPopException

>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.push()
{}
>>> c['foo'] = 'second level'
>>> c['foo']
'second level'
>>> c.pop()
{'foo': 'second level'}
>>> c['foo']
'first level'
>>> c['foo'] = 'overwritten'
>>> c['foo']
'overwritten'
>>> c.pop()
Traceback (most recent call last):
...
ContextPopException

您也可以使用push()作为上下文管理器,以确保调用匹配的pop()

>>> c = Context()
>>> c['foo'] = 'first level'
>>> with c.push():
...     c['foo'] = 'second level'
...     c['foo']
'second level'
>>> c['foo']
'first level'

传递给push()的所有参数将传递给用于构建新的上下文级别的dict构造函数。

>>> c = Context()
>>> c['foo'] = 'first level'
>>> with c.push(foo='second level'):
...     c['foo']
'second level'
>>> c['foo']
'first level'
语境。update(other_dict)[source]

push()pop()外,Context对象还定义了一个update()方法。 这个工作方式就像push(),但将一个字典作为参数,并将该字典推送到堆栈而不是空的。

>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.update({'foo': 'updated'})
{'foo': 'updated'}
>>> c['foo']
'updated'
>>> c.pop()
{'foo': 'updated'}
>>> c['foo']
'first level'

push()一样,您可以使用update()作为上下文管理器,以确保调用匹配的pop()

>>> c = Context()
>>> c['foo'] = 'first level'
>>> with c.update({'foo': 'second level'}):
...     c['foo']
'second level'
>>> c['foo']
'first level'

some custom template tags中使用Context作为堆栈。

语境。扁平化 T0>()¶ T1>

使用flatten()方法,您可以将整个Context堆栈作为一个包含内置变量的字典。

>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.update({'bar': 'second level'})
{'bar': 'second level'}
>>> c.flatten()
{'True': True, 'None': None, 'foo': 'first level', 'False': False, 'bar': 'second level'}

flatten()方法在内部也用于使Context对象具有可比性。

>>> c1 = Context()
>>> c1['foo'] = 'first level'
>>> c1['bar'] = 'second level'
>>> c2 = Context()
>>> c2.update({'bar': 'second level', 'foo': 'first level'})
{'foo': 'first level', 'bar': 'second level'}
>>> c1 == c2
True

来自flatten()的结果在单元测试中可以用来比较Contextdict

class ContextTest(unittest.TestCase):
    def test_against_dictionary(self):
        c1 = Context()
        c1['update'] = 'value'
        self.assertEqual(c1.flatten(), {
            'True': True,
            'None': None,
            'False': False,
            'update': 'value',
        })

使用RequestContext

RequestContext(request, dict_=None, processors=None)[source]

Django带有一个特殊的Context类,django.template.RequestContext,它与正常的django.template.Context有些不同。 第一个区别是它将一个HttpRequest作为第一个参数。 例如:

c = RequestContext(request, {
    'foo': 'bar',
})

第二个不同之处在于它根据引擎的context_processors配置选项自动使用几个变量填充上下文。

context_processors选项是一个名为上下文处理器的可调用列表,它将请求对象作为它们的参数,并返回要合并到上下文中的项目字典。 在默认生成的设置文件中,默认模板引擎包含以下上下文处理器:

[
    'django.template.context_processors.debug',
    'django.template.context_processors.request',
    'django.contrib.auth.context_processors.auth',
    'django.contrib.messages.context_processors.messages',
]

In addition to these, RequestContext always enables 'django.template.context_processors.csrf'. 这是管理员和其他contrib应用程序所需的与安全相关的上下文处理器,并且在意外错误配置的情况下,它被有意地硬编码并且不能在context_processors选项中关闭。

每个处理器按顺序应用。 这意味着,如果一个处理器向上下文添加一个变量,第二个处理器添加一个名称相同的变量,则第二个处理器将覆盖第一个。 下面介绍默认的处理器。

当应用上下文处理器时

上下文处理器应用于上下文数据之上。 这意味着上下文处理器可能会覆盖您提供给ContextRequestContext的变量,因此请注意避免变量名与您的上下文处理器提供的变量名重叠。

如果要使上下文数据优先于上下文处理器,请使用以下模式:

from django.template import RequestContext

request_context = RequestContext(request)
request_context.push({"my_name": "Adrian"})

Django这样做是为了允许上下文数据覆盖诸如render()TemplateResponse之类的API中的上下文处理器。

另外,您可以使用可选的第三个位置参数processorsRequestContext一个额外的处理器列表。 In this example, the RequestContext instance gets a ip_address variable:

from django.http import HttpResponse
from django.template import RequestContext, Template

def ip_address_processor(request):
    return {'ip_address': request.META['REMOTE_ADDR']}

def client_ip_view(request):
    template = Template('{{ title }}: {{ ip_address }}')
    context = RequestContext(request, {
        'title': 'Your IP Address',
    }, [ip_address_processor])
    return HttpResponse(template.render(context))

内置的模板上下文处理器

以下是每个内置处理器的功能:

django.contrib.auth.context_processors.auth

auth()[source]

如果这个处理器被启用,每个RequestContext将包含这些变量:

  • user - 代表当前登录用户的auth.User实例(或者AnonymousUser实例,如果客户端未登录) 。
  • perms - django.contrib.auth.context_processors.PermWrapper的一个实例,表示当前登录的用户拥有的权限。

django.template.context_processors.debug

debug()[source]

If this processor is enabled, every RequestContext will contain these two variables – but only if your DEBUG setting is set to True and the request’s IP address (request.META['REMOTE_ADDR']) is in the INTERNAL_IPS setting:

  • debug - True 您可以在模板中使用它来测试您是否处于DEBUG模式。
  • sql_queries - 列表 { 'SQL': ... '时间': ...} 字典,代表在请求期间发生的每个SQL查询以及需要多长时间。 该列表按数据库别名顺序查询。 它在访问时被懒惰地生成。

django.template.context_processors.i18n

如果启用这个处理器,每个RequestContext将包含这两个变量:

  • LANGUAGES - LANGUAGES设置的值。
  • LANGUAGE_CODErequest.LANGUAGE_CODE, if it exists. 否则,就是LANGUAGE_CODE设置的值。

有关更多信息,请参阅Internationalization and localization

django.template.context_processors.media

如果此处理器已启用,则每个RequestContext将包含一个变量MEDIA_URL,提供MEDIA_URL设置的值。

django.template.context_processors.static

static()[source]

如果此处理器已启用,则每个RequestContext将包含一个变量STATIC_URL,提供STATIC_URL设置的值。

django.template.context_processors.csrf

该处理器添加csrf_token模板标签所需的令牌,以防止Cross Site Request Forgeries

django.template.context_processors.request

如果启用了这个处理器,每个RequestContext将包含一个变量request,它是当前的HttpRequest

django.template.context_processors.tz

tz()[source]

如果此处理器已启用,则每个RequestContext将包含一个变量TIME_ZONE,提供当前活动时区的名称。

django.contrib.messages.context_processors.messages

如果启用这个处理器,每个RequestContext将包含这两个变量:

编写自己的上下文处理器

上下文处理器有一个非常简单的接口:它是一个Python函数,它接受一个参数,一个HttpRequest对象,并返回一个添加到模板上下文的字典。 每个上下文处理器必须返回一个字典。

自定义上下文处理器可以在你的代码库中的任 所有的Django关心的是你的自定义上下文处理器是由你的TEMPLATES设置中的'context_processors'选项指定的 - 或者是context_processors如果您直接使用Engine,请使用Engine

载入模板

通常,您将模板存储在文件系统的文件中,而不是自己使用底层的Template API。 将模板保存在指定为模板目录的目录中。

Django根据您的模板加载设置(请参阅下面的“加载器类型”)在许多地方搜索模板目录,但指定模板目录最基本的方法是使用DIRS选项。

DIRS选项

Tell Django what your template directories are by using the DIRS option in the TEMPLATES setting in your settings file — or the dirs argument of Engine. 这应该被设置为包含模板目录完整路径的字符串列表:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            '/home/html/templates/lawrence.com',
            '/home/html/templates/default',
        ],
    },
]

只要目录和模板可以被Web服务器读取,你的模板就可以到达任何你想要的地方。 他们可以有任何你想要的扩展名,如.html.txt,或者根本没有扩展名。

请注意,即使在Windows上,这些路径也应该使用Unix风格的正斜杠。

加载器类型

默认情况下,Django使用基于文件系统的模板加载器,但Django提供了一些其他模板加载器,它们知道如何从其他源加载模板。

Some of these other loaders are disabled by default, but you can activate them by adding a 'loaders' option to your DjangoTemplates backend in the TEMPLATES setting or passing a loaders argument to Engine. loaders should be a list of strings or tuples, where each represents a template loader class. 以下是Django附带的模板加载器:

django.template.loaders.filesystem.Loader

文件系统。装载机 T0> ¶ T1>

根据DIRS加载文件系统中的模板。

这个加载器默认是启用的。 但是,在将DIRS设置为非空列表之前,它不会找到任何模板:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR, 'templates')],
}]

您也可以覆盖'DIRS'并指定特定文件系统加载器的特定目录:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'OPTIONS': {
        'loaders': [
            (
                'django.template.loaders.filesystem.Loader',
                [os.path.join(BASE_DIR, 'templates')],
            ),
        ],
    },
}]
在Django 1.11中更改:

添加了为特定文件系统加载器指定目录的功能。

django.template.loaders.app_directories.Loader

app_directories。装载机 T0> ¶ T1>

从文件系统的Django应用程序加载模板。 对于INSTALLED_APPS中的每个应用程序,加载器查找templates子目录。 如果该目录存在,Django将在其中查找模板。

这意味着您可以使用您的个人应用程序存储模板。 这也使得使用默认模板来分发Django应用程序变得很容易。

例如,对于这个设置:

INSTALLED_APPS = ['myproject.polls', 'myproject.music']

…then get_template('foo.html') will look for foo.html in these directories, in this order:

  • /路径/到/ myproject的/调查/模板/
  • /路径/到/ myproject的/音乐/模板/

...将使用它找到的第一个。

INSTALLED_APPS的顺序非常重要! For example, if you want to customize the Django admin, you might choose to override the standard admin/base_site.html template, from django.contrib.admin, with your own admin/base_site.html in myproject.polls. You must then make sure that your myproject.polls comes before django.contrib.admin in INSTALLED_APPS, otherwise django.contrib.admin’s will be loaded first and yours will be ignored.

请注意,加载器在首次运行时执行优化:它缓存一个列表,其中INSTALLED_APPS包具有templates子目录。

您可以通过将APP_DIRS设置为True来启用该加载器:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'APP_DIRS': True,
}]

django.template.loaders.cached.Loader

缓存。装载机 T0> ¶ T1>

默认情况下(当DEBUGTrue时),模板系统每次渲染时都会读取和编译模板。 虽然Django模板系统非常快,但是阅读和编译模板的开销可能会相加。

您可以使用应该包装的其他加载程序的列表来配置缓存的模板加载程序。 包装的装载机在第一次遇到时用于定位未知的模板。 缓存的加载器然后将编译的Template存储在内存中。 缓存的Template实例返回后续请求加载相同的模板。

This loader is automatically enabled if OPTIONS['loaders'] isn’t specified and OPTIONS['debug'] is False (the latter option defaults to the value of DEBUG).

你也可以用一些自定义模板加载器来启用模板缓存,使用如下设置:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR, 'templates')],
    'OPTIONS': {
        'loaders': [
            ('django.template.loaders.cached.Loader', [
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader',
                'path.to.custom.Loader',
            ]),
        ],
    },
}]

注意

所有内置的Django模板标签都可以安全地用于缓存的加载器,但是如果您使用来自第三方包的自定义模板标签,或者您自己编写的自定义模板标签,则应确保Node 有关更多信息,请参阅template tag thread safety considerations

在Django 1.11中更改:

添加了debug False时自动启用缓存模板加载器的功能。

django.template.loaders.locmem.Loader

locmem。装载机 T0> ¶ T1>

从Python字典加载模板。 这对测试非常有用。

这个加载器将模板字典作为第一个参数:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'OPTIONS': {
        'loaders': [
            ('django.template.loaders.locmem.Loader', {
                'index.html': 'content here',
            }),
        ],
    },
}]

该加载器默认是禁用的。

Django按照'loaders'选项的顺序使用模板加载器。 它使用每个加载器,直到加载器找到一个匹配。

自定义加载器

可以使用自定义模板加载器从其他来源加载模板。 定制Loader类应该从django.template.loaders.base.Loader继承并定义get_contents()get_template_sources()

加载器方法

Loader[source]

加载来自给定源的模板,如文件系统或数据库。

get_template_sources(template_name)[source]

对每个可能的来源采用template_name并产生Origin实例的方法。

例如,文件系统加载器可以接收'index.html'作为template_name参数。 该方法将产生index.html的完整路径的起点,因为它出现在加载器查看的每个模板目录中。

该方法不需要验证模板是否存在于给定的路径上,但是应该保证路径是有效的。 例如,文件系统加载器确保路径位于有效的模板目录下。

get_contents T0>(来源 T1>)¶ T2>

返回给定一个Origin实例的模板的内容。

这是文件系统加载程序从文件系统读取内容的地方,或者是数据库加载程序从数据库读取的地方。 如果匹配模板不存在,则会引发TemplateDoesNotExist错误。

get_templatetemplate_nameskip = None[source]

通过循环来自get_template_sources()的结果并调用get_contents(),为给定的template_name返回一个Template对象。 这将返回第一个匹配的模板。 如果找不到模板,则引发TemplateDoesNotExist

可选的skip参数是扩展模板时要忽略的原点列表。 这允许模板扩展其他相同名称的模板。 它也用来避免递归错误。

通常,为自定义模板加载器定义get_template_sources()get_contents()就足够了。 get_template() will usually not need to be overridden.

建立你自己的

例如,阅读Django内置装载器的源代码

模板原点

模板有一个origin,其中包含属性,取决于它们从中加载的源。

Origin(name, template_name=None, loader=None)[source]
名称 T0> ¶ T1>

模板加载器返回的模板路径。 对于从文件系统读取的加载程序,这是模板的完整路径。

如果模板是直接实例化的,而不是通过模板加载器,则这是一个<unknown_source>的字符串值。

TEMPLATE_NAME T0> ¶ T1>

传递给模板加载器的模板的相对路径。

如果模板是直接实例化的,而不是通过模板加载器实现的,则这是None

装载机 T0> ¶ T1>

构建此Origin的模板加载器实例。

如果模板是直接实例化的,而不是通过模板加载器实现的,则这是None

django.template.loaders.cached.Loader requires all of its wrapped loaders to set this attribute, typically by instantiating the Origin with loader=self.