2011-10-17 78 views
8

我在我的Django項目中實現了一個自定義權限應用程序,並且我失去了如何實現自定義模板標記來檢查特定對象實例的登錄用戶權限以及根據檢查結果顯示一段HTML。if..else自定義模板標記

我現在是(僞):

{% check_permission request.user "can_edit" on article %} 
    <form>...</form> 
{% endcheck %} 

( 'check_permission' 是我的自定義模板標籤)。

templatetag接受用戶,權限和對象實例並返回封閉的HTML(表單)。目前這工作正常。

我想不過的事情,是這樣的:

{% if check_permission request.user "can_edit" on article %} 
    <form>...</form> 
{% else %} 
    {{ article }} 
{% endif %} 

我讀過有關the assignment tag,但我擔心的是,我會污染上下文變量空間與這個(指我可能覆蓋之前許可上下文變量)。換句話說,由於上下文變量是在不同的層次上定義的(視圖,我的中間件,現在這個分配模板標籤),我擔心可維護性。

回答

13

您可以在if語句中使用模板過濾器。所以,你可以重寫你的代碼作爲一個過濾器:

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

請注意,這是棘手的多個不同類型的參數傳遞給過濾器,所以你可能會想每許可使用一個過濾器,上面我用check_can_edit

+0

謝謝,過濾器確實是一個選項。然而,我預見了不同的權限(不僅僅是實例上的基本CRUD,還有一些非常具體的權限),這意味着我必須創建相同數量的自定義模板過濾器。也許我應該重新考慮我的自定義權限模型。如果你認爲將多個參數傳遞給過濾器很棘手,你的意思是可能的嗎?我原以爲不是,所以你可以澄清這一點? – LaundroMat

+1

更新到未來的訪問者:我想我會試着用鏈式過濾器來解決它(例如'{{request.user | has_permission:「entries.entry.can_edit,」| has_permission_on:article}}'自定義has_permission模板過濾器返回用戶和所需的權限,然後has_permission_on接受這些值,根據文章變量檢查它們並返回True或False。 – LaundroMat

12

如果你願意編寫更多的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。

+0

真正的答案在這裏 – snakesNbronies