在自定义模板标签中解析 Django 自定义模板标签

Posted

技术标签:

【中文标题】在自定义模板标签中解析 Django 自定义模板标签【英文标题】:Parsing a Django custom template tag within a custom template tag 【发布时间】:2015-01-20 05:21:01 【问题描述】:

我有一个有效的自定义模板标签。我想允许我的 Django 管理界面用户将该模板标签放在一个平面页面中并让它正确呈现。但是,当尝试访问呈现的平面页面时,我收到 500 服务器错误。调试控制台打印TemplateSyntaxError: Invalid block tag: 'requesturl'。是否有某种我不知道的自定义模板标签加载优先级?

这是我的自定义模板标签:

from django import template
import requests

register = template.Library()

def getrequest(url):
    """
    Simple request object
    to GET another file
    """
    try:
        r = requests.get(url)
    except requests.exceptions.RequestException as e:
        raise IOError(e)
    except requests.exceptions.HTTPError as e:
        raise IOError(e)

    if r.status_code != 200:
        raise IOError('Non 200 response returned')
    else:
        return r.content

@register.tag(name="requesturl")
def do_requesturl(parser, token):
    """
    tag usage % requesturl object.textfield %
    """
    try:
        tag_name, uri = token.split_contents();
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires a single URI string argument" % token.contents.split()[0]
    if not (uri[0] == uri[-1] and uri[0] in ('"', "'")):
        raise template.TemplateSyntaxError("%r tag's URI should be in quotes" % tag_name)
    return RequestUrlNode(uri[1:-1])

class RequestUrlNode(template.Node):
    def __init__(self, uri):
        self.uri = uri

    def render(self, context):
        try:
            pagecontent = getrequest(self.uri)
            return pagecontent
        except template.VariableDoesNotExist, template.TemplateSyntaxError:
            return 'Error rendering', self.uri

我可以将它放到我的任何 Django 模板中,定义一个 URL(在模板本身中),它使用 requests 模块来获取指定网页的内容并将其呈现在模板中:

% extends "site_layout.html" %
% load requesturl %
% requesturl "http://textfiles.com/100/914bbs.txt" %

太好了。现在,下一步是我希望我的用户能够通过在flatpages.content 字段中添加模板标签来在默认的 Django 襟翼应用程序中执行此操作,如下面的屏幕截图所示:

请注意,我已确保我使用的是特定的平面页面模板,而不是默认模板。

为了评估标签,我按照this SO answer 中的步骤进行操作。在我尝试评估我自己的自定义模板标签之前,我使用内置的 Django 模板标签和过滤器进行了测试,它就像一个魅力。下面是 Django 内置模板过滤器 (lower) 和标签 (now) 的示例:

以及它是如何呈现的:

然而,当我尝试输入我自己的自定义模板标签时,我得到了可怕的TemplateSyntaxError: Invalid block tag: 'requesturl'。下面是我的平面解析模板标签:

from django import template

register = template.Library()

@register.tag(name="evaluate")
def do_evaluate(parser, token):
    """
    tag usage % evaluate object.textfield %
    """
    try:
        tag_name, variable = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0]
    return EvaluateNode(variable)

class EvaluateNode(template.Node):
    def __init__(self, variable):
        self.variable = template.Variable(variable)

    def render(self, context):
        try:
            content = self.variable.resolve(context)
            t = template.Template(content)
            return t.render(context)
        except template.VariableDoesNotExist, template.TemplateSyntaxError:
            return 'Error rendering', self.variable

我不知道为什么我可以分别做这两个部分,但是当我尝试将它们结合起来时,我得到了错误:

File "/path/to/virtualenv/lib/python2.7/site-packages/django/template/base.py", line 332, in invalid_block_tag
raise self.error(token, "Invalid block tag: '%s'" % command)
TemplateSyntaxError: Invalid block tag: 'requesturl'

我唯一能想到的是我的自定义模板标签没有在 Django 中注册,但是如果它直接嵌入到 flatpages 模板中为什么会起作用呢?是否有某种底层模板标签注册表,或者我的 EvaluateNode 类没有做我认为它正在做的事情?

提前致谢!

【问题讨论】:

【参考方案1】:

在我看来,这不是一个适当的解决方案,但它是我现在部署的一种解决方法。我最终使用了预先存在的 Django Server Side Includes 模板标签 % ssi % 并包含来自文件系统的文件。我曾希望我的用户能够包含系统外部的文件,但对于我的用例,我可以只包含 Django 安装的本地文件。

有人可能会争辩说,无论如何,我试图做的事情本质上是不安全的,强制我的用户只包含 Django 系统本地的那些文件要安全得多。它仍然没有回答我原来的问题,这个问题更多的是关于自定义模板标签的注册和使用,而不是关于实际的实际用例。

【讨论】:

以上是关于在自定义模板标签中解析 Django 自定义模板标签的主要内容,如果未能解决你的问题,请参考以下文章

Django 如何将自定义变量传递给上下文以在自定义管理模板中使用?

如何在自定义模板中使用 Django 的管理员布尔图标?

Request.GET 在自定义 HTML Django Rest Framework 渲染器模板中不可用

Django自定义simple_tag和filter

Django之博客系统:自定义模板标签

JQuery 在 Django 自定义模板标签的模板中不起作用