2010-09-22 81 views
3

我试图创建一个简单的Django模板标签来显示或隐藏在我的网站上提交的评论旁边的“删除”链接。如何为访问控制编写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 

回答

2

OK,这是我做到了......

标签用于这样的模板:

{% 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) 

完成。最后,它会一直很简单,只需使用内置的{%如果%}标签做这种比较,但因为我有其他的每个对象的授权做的,我会继续打造出来的这些自定义“access_tags”。此外,模板代码看上去非常整洁:)

+0

冷静的解决方案,我适应它,所以你可以检查用户权限。你也可以将它们嵌套在一起,这非常适合!谢谢 – 2017-07-25 13:59:09

2

已经有一个项目,目的是做什么你想做。

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

Django 1.2在模板中也包含用户permissions

+0

感谢尼克,请看我上面的更新,为什么Django的内置权限可能不会在我的情况下工作。乍一看,全力以赴的应用似乎过度杀伤,但我会一一检查出来。感谢您的回答。 – mitchf 2010-09-22 22:46:19

2

这个怎么样...创建一个自定义标记,writes a variable in the context,然后测试使用{% if %}

它会是这样的变量:

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

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

好运

+0

这将如何工作,如果有页面其中的登录用户已删除的权限3.不会“has_access”不断改写,最终设置为任何的最后一个值是在10个评论? – mitchf 2010-09-22 23:31:02

+1

好,你只需要调用每个评论【检查_ACCESS} ...但你已经找到自己的解决方案=)F'm总是感到惊讶的是这样一个简单的测试如何,变得这么难在Django做...这就是为什么PHP永远不会死! – pleasedontbelong 2010-09-23 07:45:31

+0

谢谢gladontbelong,我感谢帮助。 – mitchf 2010-09-23 12:53:35