简体   繁体   English

处理自定义 Django 模板标签中的条件块

[英]Handling a conditional block in a custom Django template tag

I have a custom Django template tag that acts as a conditional block:我有一个用作条件块的自定义 Django 模板标签:

{% if_has_permission request "some_permission" %}
<div>
    <input type="text" name="sample_1">
    <label><input type="checkbox" name="enable_it"> Enable</label>
</div>
{% endif_has_permission %}

In this example, if the request object doesn't have the appropriate permission ( some_permission in this case), the block doesn't get rendered.在此示例中,如果请求对象没有适当的权限(在本例中为some_permission ),则不会呈现该块。 However, as soon as I inject a conditional into this block (using the {% if %} template tag), I get a TemplateSyntaxError:但是,一旦我将条件注入到这个块中(使用{% if %}模板标记),我就会得到一个 TemplateSyntaxError:

{% if_has_permission request "some_permission" %}
<div>
    <input type="text" name="sample_1">
    <label><input type="checkbox" name="enable_it" {% if isChecked %}checked="checked"{% endif %}> Enable</label>
</div>
{% endif_has_permission %}

The error I see is:我看到的错误是:

Invalid block tag: 'endif', expected 'endblock'无效的块标记:'endif',应为'endblock'

What, if anything, can I do to allow conditional expressions within my custom tag?如果有的话,我可以做些什么来允许在我的自定义标签中使用条件表达式? I'm pretty sure that {% if %} is the only case I'll ever need to allow, though the occasional {% for %} might also be useful.我很确定{% if %}是我需要允许的唯一情况,尽管偶尔{% for %}也可能有用。

Here's my custom template tag code:这是我的自定义模板标记代码:

@register.tag
def if_has_permission(parser, token):
    try:
        args = token.split_contents()
        tag_name, request, to_check = args[0], args[1], args[2]
        opts = None
        if(len(args) > 3):
            opts = args[3:]
    except IndexError:
        raise template.TemplateSyntaxError("Tag %r requires at least two arguments" % tag_name)

    if(not (to_check[0] == to_check[-1] and to_check[0] in ('"', "'"))):
        raise template.TemplateSyntaxError("The second argument to tag %r must be in quotes" % tag_name)

    nodelist_true = parser.parse(('endif_has_permission'),)
    parser.delete_first_token()
    return CheckPermissionNode(request, to_check[1:-1], opts, nodelist_true)

class CheckPermissionNode(template.Node):
    def __init__(self, request, to_check, opts, nodelist_true):
        self.request = template.Variable(request)
        self.to_check = to_check
        self.opts = opts
        self.nodelist_true = nodelist_true

    def render(self, context):
        rq = self.request.resolve(context)

        # Admins can always see everything
        if(rq.session['is_admin']):
            return self.nodelist_true.render(context)

        # Check to see if any of the necessary permissions are present
        hasPerm = False
        checkList = self.to_check.split('|')
        for c in checkList:
            if(c in rq.session['perms']):
                hasPerm = True
                break

        if(hasPerm):
            return self.nodelist_true.render(context)
        else:
            return ''

Templatetags are not like blocks - think about them more like as methods .模板标签不像块——把它们更像是方法 The error you are getting is due to bad syntax then.您得到的错误是由于语法错误造成的。

To implement something like this just create a filter that will check a condition (exactly like your tag is doing now) and will return True or False then use it like要实现这样的东西,只需创建一个过滤器来检查条件(就像你的标签现在所做的一样)并返回TrueFalse然后像这样使用它

    {% if request|your_filter_name:"condition" %}
        <p> do_sth </p>
    {% endif %}

by using default django-template if block通过使用默认的 django-template if


Please notice that you cannot use tags in if blocks - that's why you need to change it to being filter (by adding register.filter instead of register.tag ).请注意,您不能在if块中使用标签 - 这就是为什么您需要将其更改为过滤器(通过添加register.filter而不是register.tag )。 Nothing will change but syntax:除了语法,什么都不会改变:

    request|your_filter:"condition"

instead of代替

    your_tag request "condition"

As it turns out, this is indeed possible.事实证明,这确实是可能的。 There's a typo in the if_has_permission routine: if_has_permission例程中有一个错字:

nodelist_true = parser.parse(('endif_has_permission'),)

should instead become:应该改为:

nodelist_true = parser.parse(('endif_has_permission',))

Note that the comma was in the wrong place!请注意,逗号在错误的位置! The parse function expects a tuple. parse函数需要一个元组。 Fixing this typo prevents things from going awry.修复这个错字可以防止事情出错。

As an aside, I stumbled upon this question today after running into the exact same problem.顺便说一句,在遇到完全相同的问题后,我今天偶然发现了这个问题。 Imagine my surprise when I found that I was the original asker, nearly five years ago;想象一下,大约五年前,当我发现自己是最初的提问者时,我的惊讶; ha!哈!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM