if..else自定义模板标记

Lau*_*Mat 9 django django-templates

我执行我的Django项目自定义权限的应用程序,而我失去了对如何实现自定义的模板标签来检查用户的特定对象实例权限的记录并显示基于结果的一块HTML的支票.

我现在拥有的是(伪代码):

{% check_permission request.user "can_edit" on article %}
    <form>...</form>
{% endcheck %}
Run Code Online (Sandbox Code Playgroud)

('check_permission'是我的自定义模板标记).

templatetag接受用户,权限和对象实例,并返回随附的HTML(表单).这目前工作正常.

然而,我想做的是:

{% if check_permission request.user "can_edit" on article %}
    <form>...</form>
{% else %}
    {{ article }}
{% endif %}
Run Code Online (Sandbox Code Playgroud)

我已经阅读了有关赋值标记的内容,但我担心的是我会用此污染上下文变量空间(这意味着我可能会覆盖以前的权限上下文变量).换句话说,由于上下文变量是在不同的层次上定义的(视图,我的中间件,现在这个赋值模板标签),我担心可维护性.

Dan*_*man 16

您可以在if语句中使用模板过滤器.因此,您可以将标记重写为过滤器:

{% if request.user|check_can_edit:article %}
Run Code Online (Sandbox Code Playgroud)

请注意,将不同类型的多个参数传递给过滤器很棘手,因此您可能希望每个权限使用一个过滤器,我已经使用过check_can_edit.

  • 向未来的访客更新:我想我将尝试使用链式过滤器解决该问题(例如`{{request.user | has_permission:“ entries.entry.can_edit,” | has_permission_on:article}}`。自定义has_permission模板过滤器会返回用户和所需的权限后,has_permission_on将采用这些值,并根据article变量对其进行检查,并返回True或False。 (2认同)

cla*_*ete 16

如果你愿意编写更多的python代码来提高模板的可读性,你绝对可以做到!:)

如果要在变量上使用变量,则需要自己解析标记内容,甚至是所需的参数然后解析它们.

下面实现的标记可以像这样使用:

{% load mytag %}
{% mytag True %}Hi{% else %}Hey{% endmytag %} Bro
Run Code Online (Sandbox Code Playgroud)

或者使用变量:

{% mytag myobject.myflag %}Hi{% else %}Hey{% endmytag %} Bro
Run Code Online (Sandbox Code Playgroud)

所以,这就是我做的方式:

from django.template import Library, Node, TemplateSyntaxError

register = Library()

@register.tag
def mytag(parser, token):
    # Separating the tag name from the "test" parameter.
    try:
        tag, test = token.contents.split()
    except (ValueError, TypeError):
        raise TemplateSyntaxError(
            "'%s' tag takes two parameters" % tag)

    default_states = ['mytag', 'else']
    end_tag = 'endmytag'

    # Place to store the states and their values
    states = {}

    # Let's iterate over our context and find our tokens
    while token.contents != end_tag:
        current = token.contents
        states[current.split()[0]] = parser.parse(default_states + [end_tag])
        token = parser.next_token()

    test_var = parser.compile_filter(test)
    return MyNode(states, test_var)


class MyNode(Node):
    def __init__(self, states, test_var):
        self.states = states
        self.test_var = test_var

    def render(self, context):
        # Resolving variables passed by the user
        test_var = self.test_name.resolve(context, True)

        # Rendering the right state. You can add a function call, use a
        # library or whatever here to decide if the value is true or false.
        is_true = bool(test_var)
        return self.states[is_true and 'myvar' or 'else'].render(context)
Run Code Online (Sandbox Code Playgroud)

就是这样.HTH.