在模板标签中获取模板名称(Django)

时间:2011-11-23 09:55:29

标签: python django django-templates

有没有办法在模板标签中获取模板名称(被解析)? 我已经阅读了搜索但没有找到任何内容,只有之前的帖子 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

的人来说,整个标签有点像占位符

2 个答案:

答案 0 :(得分:3)

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

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

丹尼尔罗斯曼在评论中提到,如果你能详细说明你实际想要实现的目标,那么可能有更好的方法来实现你想要的。没有冒犯,但这听起来像是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()
  4. 为了测试这一点,我定义了以下标签,它只返回大写字母中的模板名称:

    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进行调用。我个人更喜欢这个,因为这使它成为现有渲染功能的替代品。