2010-09-22 82 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