有没有办法在模板标签中获取模板名称(被解析)? 我已经阅读了搜索但没有找到任何内容,只有之前的帖子 Getting the template name in django template
这对我没有多大帮助,因为答案依赖于settings.DEBUG是真的,在我的情况下不可能。
我真的不知道从哪里开始,所以欢迎任何建议:)
修改
基本上我想要的是创建一个可插入的标签,当它渲染时它会检查一个Tag对象,这将是标签对象的来源
class Tag(models.Model):
template = models.CharFIeld(max_length=50)
name = models.CharField(max_length=100)
plugins = models.ForeignKey(PluginBase)
如果是一个标签对象,那么它会显示所有插件对象,如果没有,它会创建一个标签对象,该标签对象是模板标签和模板名称中提供的名称唯一,如果获取模板名称是不可能的话,我猜我可以让每个名字都独一无二。对于那些熟悉django-cms
的人来说,整个标签有点像占位符答案 0 :(得分:3)
查看源代码,虽然Template
对象可以访问模板名称(通过.name
),但此值永远不会传递给Parser对象,因此无法使用模板标签。
模板名称有多种方式可供模板本身使用(通过将其添加到上下文中),但不能在模板标签中使用。
丹尼尔罗斯曼在评论中提到,如果你能详细说明你实际想要实现的目标,那么可能有更好的方法来实现你想要的。没有冒犯,但这听起来像是XY problem。
出于学术兴趣,我有一个快速的小提琴,看看是否有可能。据我所知,有可能但不是没有改变或猴子修补django源。
注意:以下是不是推荐的解决方案,只是暗示了实际执行此操作可能需要的内容。不得用于生产代码。
通过以下更改修改django.template.base.py
,我们将.template_name
属性添加到解析器对象,使其可用于模板标记。
compile_string
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源永远不是一个好的解决方案,并且在迁移到不同版本时会受到各种各样的痛苦。
答案 1 :(得分:2)
您可以使用上下文处理器执行此操作,但我不确定这些是否可以访问模板的名称。
可以为你做的渲染调用创建一个包装器。假设您目前执行以下操作:
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
”,并替换所有{ {1}}使用render
进行调用。我个人更喜欢这个,因为这使它成为现有渲染功能的替代品。