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

时间:2014-11-21 23:12:33

标签: python django django-templates

我有一个有效的自定义模板标记。我想允许我的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模块获取指定网页的内容并在模板中呈现它: / p>

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

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

screenshot of flat page entry

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

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

Adding built-in template tags and filters to the flatpages content textarea

它是如何呈现的:

The flatpage template tags rendered

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

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 个答案:

答案 0 :(得分:0)

这不是我眼中的适当解决方案,但这是我现在部署的解决方法。我最终使用预先存在的Django Server Side Includes模板标记{% ssi %}并包含文件系统中的文件。我希望我的用户能够在系统之外包含文件,但对于我的用例,我可以只使用包含Django安装本地文件。

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