Django if..else自定义模板标记

Django if..else自定义模板标记,django,django-templates,Django,Django Templates,我正在Django项目中实现一个自定义权限应用程序,我不知道如何实现一个自定义模板标记,该标记检查登录用户对特定对象实例的权限,并根据检查结果显示一段HTML 我现在拥有的是(伪代码): {%check\u权限请求。用户“可以编辑”文章%} ... {%endcheck%} ('check_permission'是我的自定义模板标记) templatetag接收用户、权限和对象实例,并返回附带的HTML(表单)。这目前效果很好 然而,我想做的是: {% if check_permission

我正在Django项目中实现一个自定义权限应用程序,我不知道如何实现一个自定义模板标记,该标记检查登录用户对特定对象实例的权限,并根据检查结果显示一段HTML

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

{%check\u权限请求。用户“可以编辑”文章%}
...
{%endcheck%}
('check_permission'是我的自定义模板标记)

templatetag接收用户、权限和对象实例,并返回附带的HTML(表单)。这目前效果很好

然而,我想做的是:

{% if check_permission request.user "can_edit" on article %}
    <form>...</form>
{% else %}
    {{ article }}
{% endif %}
{%if check\u permission request.user“can\u edit”on article%}
...
{%else%}
{{条款}
{%endif%}

我已经读过,但我担心我会用它污染上下文变量空间(这意味着我可能会覆盖以前的权限上下文变量)。换句话说,由于上下文变量是在不同的级别上定义的(视图、我的例子中的中间件以及现在的分配模板标记),我担心可维护性。

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

{% if request.user|check_can_edit:article %}

请注意,将多个不同类型的参数传递给一个筛选器是很棘手的,因此您可能希望每个权限使用一个筛选器,上面我使用了
check\u can\u edit

如果您愿意编写更多的python代码来提高模板的可读性,您肯定可以这样做!:)

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

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

{% load mytag %}
{% mytag True %}Hi{% else %}Hey{% endmytag %} Bro
或使用变量:

{% mytag myobject.myflag %}Hi{% else %}Hey{% endmytag %} Bro
我是这样做的:

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)

就这样。HTH.

在这种情况下,最好的解决方案是使用自定义过滤器。如果不想为自定义标记编写长代码。另外,如果您不想复制/粘贴其他代码。 这里有一个例子

内部模板标签

内模板


由于其中一个主要的常用方法是在模型的自定义方法中使用request.user或任何特定对象(id),因此过滤单个对象或用户是最简单的方法。:)

在Django 2中,赋值标记被simple_tag()替换,但您可以将自定义标记结果存储为模板变量:

{% mytag myobject.myflag %}Hi{% else %}Hey{% endmytag %} Bro
#我假设check_权限接收用户和文章,
#检查用户是否可以编辑文章并返回True或False
{%check_权限用户文章作为权限_清除%}
{%如果权限\已清除%}
...
{%else%}
{{条款}
{%endif%}

查看关于自定义模板标签的当前文档:

谢谢,过滤器确实是一个选项。然而,我预见到不同的权限(不仅仅是实例上的基本CRUD,还有一些非常具体的权限),这意味着我必须创建等量的自定义模板过滤器。也许我应该重新考虑我的自定义权限模型。如果你说将多个参数传递给一个过滤器很棘手,你是说这是可能的吗?我原以为不是,所以你能澄清一下吗?给未来的访问者更新:我想我会尝试用链式过滤器解决这个问题(例如,
{{request.user | has|u permission:“entries.entry.can|edit,”| has|permission|on:article}
。自定义has\u权限模板筛选器返回用户和所需的权限,has\u permission\u on然后获取这些值,对照article变量检查它们并返回True或False。@自助洗衣店您是否完成过链接筛选器解决方案?如果是,您能将其作为答案共享吗?谢谢!@StephenGTuggy我已经搜索过了通过我的项目,但找不到任何东西…我想这是(另一个)被放弃的项目的一部分。很抱歉,我不能再帮你了。
register = template.Library()
def exam_available(user, skill):
    skill = get_object_or_404(Skill, id=skill)
    return skill.exam_available(user)
register.filter('exam_available', exam_available)
    {{ request.user|exam:skill.id  }}
    or
    {% if request.user|exam:skill.id  %}