在自定义模板标签中解析 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 如何将自定义变量传递给上下文以在自定义管理模板中使用?