我们可以在Django模板上使用与python相关的api吗?

时间:2020-05-27 12:56:14

标签: html django django-forms django-templates

我是Django的新手,因此没有足够的知识。所以我在Django中遇到了一些错误。

当前,我正尝试从Django模板html文件中打印变量的类型,如下所示:

<center><h2>The type of feature list report for version {%type(version)%} is<h2></center>

对于上述情况,我收到以下错误:

Invalid block tag on line 9: 'type(version)'. Did you forget to register or load this tag?

那么这里出了什么问题?我们如何从html模板文件中使用与python相关的api(例如type(),strip(),get()等)?我认为在{%....%}内部,我们可以使用与python相关的评估。我对吗?

请为此点些灯光。

3 个答案:

答案 0 :(得分:1)

如上所述,这不是DTL的原理,但是一些转换输入的函数实现为filters

此外,您可以编写自己的过滤器并支持“类型”过滤器,这将非常简单:

from django import template
from typing import Any

register = template.Library()

def filter_type(value: Any) -> str:
    return str(type(value))

register.filter('type', filter_type)

有关详细信息,请参见the documentation

Jinja和DTL的方法都是显式的,而不是隐式的:与其一味地支持任何python函数带来的所有危险,不如明确地允许它或实现它。

答案 1 :(得分:1)

有意禁用在Django模板中运行任意Python代码。除了安全问题外,原因是您项目的业务逻辑应与表示层分开。这是良好的应用程序设计的一部分。

您可以通过三种主要方法从Django模板调用操作。

  1. 传入一个函数并调用它。
  2. 使用自定义或内置的模板过滤器。
  3. 使用自定义或内置的模板标签。

传入一个函数并调用它。

从Django模板调用传入的函数是标准的。但是,它有两个警告。

  1. 该函数必须返回一个可以是字符串或可以强制为字符串的值。 (否则,模板中将不会打印任何内容。)
  2. 该函数必须没有任何必需的参数。

最常见的用例是计算值或吸气剂,例如

class Page(models.Model):
    title = models.CharField()

    def get_title(self):
        return self.title
<h1>{{ page.get_title }}</h1>

模板过滤器

有关模板过滤器的示例,请参见Melvyn's answer

模板过滤器对值进行操作。因此,对于type()之类的Python函数而言,这是完美的选择。

模板标签

已编辑:请参阅Melvyn的评论。

简单模板标签的工作方式更像一个函数。它们接受位置和关键字参数,并应再次返回值。在这里,我将不涉及包含标记或高级标记的编译和渲染,但是您可以在Django custom template tag docs中进行了解。

这是我经常在debug.py中的项目中包含的两个模板标签的示例。

import pprint
from django import template

register = template.Library()
pp = pprint.PrettyPrinter(indent=4, width=120)


@register.simple_tag(takes_context=True)
def print_context(context):
    pp.pprint(context)
    return ""


@register.simple_tag()
def print_thing(thing):
    pp.pprint(thing)
    return ""

我可以使用print_context打印终端中的当前上下文,并使用print_thing打印某些内容。

{% load debug %}
{% print_context %}

{% print_thing 'print this string' %}

您可以创建一个模板标签,该标签可以执行标准Python函数可以执行的任何操作。这是因为模板标记实际上会调用您创建的函数。

充分利用Django模板系统的约束,创建设计良好的应用程序,其中业务逻辑位于视图,模型和帮助器中,而不位于模板中。

答案 2 :(得分:0)

您可以创建一个包含类型的类,因此可以像这样调用类型:variable.type,也可以从控制器发送类型数据。 如果您需要在前端进行反应式编程逻辑,建议您使用Vue,React或Angular。