3

我徒劳地尝试创建一个简单的 Django 模板标签来显示或隐藏我网站上提交的评论旁边的“删除”链接。

简而言之,我想将评论对象传递给模板标签,确定当前登录的用户是否有权删除评论,然后显示或不显示链接。

我的模板中的用法是这样的:

{% load access_tags %}
{% if_authorized comment %}
   <a href="{% url delete_comment comment.id %}">Delete</a>
{% endif_authorized %}

请放心,如果用户有权删除评论,我也会检查相应的视图。

这种类型的标签有特定的名称吗?如果确实如此,它肯定会帮助我进行 Google 搜索。谢谢你的帮助!

更新 1:

我的网站的工作方式,有两个人可能被授权删除评论:1)评论创建者和 2)留下评论的帖子的所有者。因此,我需要根据评论确定是否存在这些条件之一。

我不认为我可以使用 Django 的内置权限系统之类的东西,因为它要求权限“按对象类型全局设置,而不是按特定对象实例设置”。

就我而言,用户“Bob”可能有权删除评论(如果他写了评论或在他创建的帖子上),但他也可能不允许删除它(如果他正在查看某人的评论别人的帖子)。

更新 2:

似乎您不能将对象传递给模板标签,只能传递字符串:“尽管您可以使用 token.split_contents() 将任意数量的参数传递给模板标签,但这些参数都被解包为字符串文字。” 我想我会传递有问题的评论对象的 id 并将其拉入标签中。

我错了,只需要访问传入的对象,例如:

self.comment.resolve(context).user 

对比

self.comment.user
4

3 回答 3

3

好吧,我就是这么弄的……

该标签在模板中的使用方式如下:

   {% load access_tags %}
   {% if_authorized comment.user object.user user %}
      <a href="{% url delete_comment comment.id %}">Delete</a>
   {% endif_authorized %}

模板标记文件名为“access_tag.py”,位于我的应用程序的“templatetags”目录中。这是“access_tag.py”的内容:

from django.template import Node, NodeList, TemplateSyntaxError
from django.template import Library, Variable, VariableDoesNotExist

register = Library()

def do_if_authorized(parser, token):
    """
    Outputs the contents of the block if the 'comment owner' or the 
    'page owner' is also the 'authenticated user'. As well, you can use
    an {% else %} tag to show text if the match fails.

    Takes three parameters:
      1) the comment owner
      2) the page owner
      3) the current authenticated user
    """
    bits = token.contents.split()
    if len(bits) != 4:
        raise TemplateSyntaxError("%s tag takes three arguments: \
                                   1) the comment owner \
                                   2) the page owner \
                                   3) the current authenticated user" % bits[0])
    nodelist_true = parser.parse(('else', 'endif_authorized'))
    token = parser.next_token()

    if token.contents == 'else':
        nodelist_false = parser.parse(('endif_authorized',))
        parser.delete_first_token()
    else:
        nodelist_false = NodeList()
    return IfAuthorizedNode(bits[1], bits[2], bits[3], nodelist_true, nodelist_false)

class IfAuthorizedNode(Node):
    def __init__(self, comment_owner, page_owner, authenticated_user, nodelist_true, nodelist_false):
        self.nodelist_true = nodelist_true
        self.nodelist_false = nodelist_false
        self.comment_owner = Variable(comment_owner)
        self.page_owner = Variable(page_owner)
        self.authenticated_user = Variable(authenticated_user)

    def render(self, context):
        try:
            comment_owner = self.comment_owner.resolve(context)
            page_owner = self.page_owner.resolve(context)
            authenticated_user = self.authenticated_user.resolve(context)
        except VariableDoesNotExist:
            return ''

        if comment_owner == authenticated_user or page_owner == authenticated_user:
            return self.nodelist_true.render(context)
        else:
            return self.nodelist_false.render(context)

register.tag('if_authorized', do_if_authorized)

完毕。最后,只使用内置的 {% if %} 标签来进行比较会很容易,但是由于我还有其他的每个对象的授权要做,所以我将继续构建这些自定义“访问标签”。另外,模板代码看起来更整洁:)

于 2010-09-23T04:08:16.083 回答
2

已经存在一个旨在做你想做的事情的项目。

django-authority允许对模板中的权限进行细粒度控制。

Django 1.2 也在模板中包含用户权限

于 2010-09-22T22:16:52.517 回答
2

这个怎么样......创建一个在上下文中写入变量的自定义标签,然后使用测试该变量{% if %}

它会是这样的:

{% check_access comment %}
{% if has_access %}
    <a href="{% url delete_comment comment.id %}">Delete</a>
{% endif %}

当然,“check_access”标签会在上下文中写入“has_access”。

祝你好运

于 2010-09-22T23:13:54.017 回答