【问题标题】:Get template name in template tag ( Django )在模板标签中获取模板名称(Django)
【发布时间】:2012-01-04 15:02:11
【问题描述】:

有没有办法在模板标签中获取模板名称(被解析)? 我已经阅读了搜索并没有发现任何东西,只有这个以前的帖子 Getting the template name in django template

这对我没有多大帮助,因为答案依赖于 settings.DEBUG 为真,在我的情况下不可能。

我真的不知道从哪里开始,所以欢迎任何建议:)

编辑

所以基本上我想要的是创建一个可插入的标签,在渲染时它会检查标签对象,这将是标签对象的来源

class Tag(models.Model):
    template = models.CharFIeld(max_length=50)
    name = models.CharField(max_length=100)
    plugins = models.ForeignKey(PluginBase)

如果有标签对象,那么它会显示所有插件对象,如果没有,它会创建一个标签对象,该标签对象对模板标签中提供的名称和模板名称是唯一的,如果无法获取模板名称,那么我猜我可以让它每个名字都是唯一的。对于熟悉 django-cms 的人来说,整个标签有点像占位符

【问题讨论】:

  • 我怀疑这是不可能的。据我所知,在标签解释完成之前,模板结构会被解析成树状模型。所以我假设你需要的信息在执行模板标签时丢失了。 (这只是一个疯狂的猜测,但我认为你应该计划另一种方式;))
  • 您的实际用例是什么?我怀疑有更好的方法来实现你想要的。

标签: python django django-templates


【解决方案1】:

您也许可以使用上下文处理器来执行此操作,但我不确定它们是否可以访问模板的名称。

可以为您执行的渲染调用制作一个包装器。假设您目前正在执行以下操作:

from django.shortcuts import render
def index(request):
    return render(request, 'app/index.html', { 'foo': 'bar', })

如果您为此创建自己的包装器,则可以在实际渲染发生之前将模板名称添加到字典中:

from django.shortcuts import render
def myrender(request, template, dictionary):
    dictionary.update({'template_name': template})
    return render(request, template, dictionary)

然后在你的视图中,将其更改如下(假设你将上述函数保存在myutils.py,并且它在你的路径上可用):

#from django.shortcuts import render <- delete this line
from myutils import myrender as render
def index(request):
    return render(request, 'app/index.html', { 'foo': 'bar', })

现在您的所有render 调用都将使用模板名称更新字典。在任何模板中,只需使用{{ template_name }} 来获取名称。当然,您也可以以类似的方式更新其他渲染函数,例如 render_to_response 等。

另外,import myrender as render 稍后可能会或可能不会让您感到困惑,因为它的命名类似于 Django 函数...如果是这样,只需在不带“as render”的情况下导入它,并将所有 render 调用替换为myrender。我个人更喜欢这个,因为这使它成为现有渲染功能的直接替代品。

【讨论】:

  • 谢谢,但是因为它是一个需要访问的模板标签,所以我并没有真正使用视图渲染功能,因为基本上我希望模板标签获取它的模板名称并对其进行一些处理.我确实同意上下文处理器,但真的不知道如何获得名称:(
  • 不渲染模板你是怎么用的?
  • 我的意思是我不会是通过视图渲染模板的人,因为它是开源的
  • 如果不修改至少一些 python 代码,我真的想不出一种方法:无论是视图本身,还是肖恩在他的回答中提到的 Django 源代码。猜猜它归结为对你的目标受众影响最小的那一个......?
【解决方案2】:

查看源代码,虽然Template 对象可以访问模板名称(通过.name),但此值永远不会传递给Parser 对象,因此不适用于模板标签。

有多种方法可以使模板名称对模板本身可用(通过将其添加到上下文中)但不在模板标签内。

正如丹尼尔·罗斯曼 (Daniel Roseman) 在 cmets 中提到的,如果您可以详细说明您实际想要实现的目标,那么可能会有更好的方法来实现您想要的目标。没有冒犯,但这听起来可能是XY problem


出于学术兴趣,我想了想看看是否可行。据我所知,这是可能的,但不是不改变或猴子修补 django 源代码。

注意:以下是不推荐的解决方案,只是暗示实际完成这项工作可能需要什么。不得用于生产代码。

通过使用以下更改修改django.template.base.py,我们将.template_name 属性添加到解析器对象,使其可用于模板标签。

  1. Added optional arg to compile_string
  2. Added template name as extra attribute to parser
  3. Passed in the template name when calling compile_string()

为了测试这一点,我定义了以下标签,它只返回大写的模板名称:

from django.template.base import Node, Library
register = Library()

class TemplateNameNode(Node):
    def __init__(self, template_name):
        self.name = template_name

    def render(self, context):
        return self.name.upper()

@register.tag
def caps_template_name(parser, token):
     return TemplateNameNode(parser.template_name)

以及以下模板:

{% load mytags %}
Template name in caps: {% caps_template_name %}

./manage.py shell 中测试时这似乎有效:

>>> from django.template import loader, Context
>>> t = loader.get_template("test.html")
>>> t.render(Context({}))
u'\nTemplate name in caps: TEST.HTML\n'

虽然这似乎可行,但我应该重申手动修补 django 源从来都不是一个好的解决方案,并且在迁移到不同版本时会遇到各种痛苦。

【讨论】: