【问题标题】:Can we use python related api's on the Django templates?我们可以在 Django 模板上使用 python 相关的 api 吗?
【发布时间】:2020-09-14 12:38:04
【问题描述】:

我是 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 相关的评估。我对吗?

请给这点点灯。

【问题讨论】:

  • 首先,您必须将值传递给您正在处理的 django 模板,就像作为上下文数据一样。那么只有你才能获得价值。你不能在这里做更多的操作。 Django 模板仅用于查看或渲染,因此只需传递它并显示它不要在这里做更多操作。这样做是个好习惯。
  • 我已经将值传递给 django 模板。那么传完值后,我们就不能再对它做任何操作了吗?
  • 要么切换到 jinja2 并将类型声明为安全函数,要么不要尝试在模板中编程(这是 Django 模板语言的理念)。
  • 这不是一个好方法@RDX 通常,只需确保您的视图将正确的数据传递给您的模板,您不需要做太多工作来确保它以 html 形式出现,只需例如,如果你想在 python 中尝试值的长度,你可以使用 len(your_data) 但这里的一个小改动是获取字符串的长度,如 {{obj.data1 |长度}}。这里 len() 的大括号不起作用。做出明智的选择。我的建议是从您的观点出发。

标签: html django django-forms django-templates


【解决方案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 函数,你必须明确地允许或实现它。

【讨论】:

    【解决方案2】:

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

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

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

    传入一个函数并调用它。

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

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

    最常见的用例是计算值或 getter,例如

    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 模板系统的约束来创建设计良好的应用程序,其中业务逻辑位于视图、模型和帮助程序中,而不是模板中。

    【讨论】:

    • 写得真好。然而:模板标签没有返回一个值。经典示例是 {% for %} 标签。我不会深入讨论函数和例程之间的区别,因为我认为没有人知道这一点了。 :)
    • 谢谢!这是一个好点。我主要考虑的是简单的标签,如果没有返回值,它将呈现None。但你是对的,包含标签和更复杂的标签的操作方式非常不同。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      • 1970-01-01
      • 2016-08-29
      • 1970-01-01
      相关资源
      最近更新 更多