2011-10-17 16 views
8

Wdrażam aplikację niestandardowych uprawnień w moim projekcie Django i nie mam pojęcia, jak zaimplementować niestandardowy znacznik szablonu, który sprawdza uprawnienia zalogowanego użytkownika dla określonej instancji obiektu i pokazuje fragment HTML na podstawie wyniku sprawdzenia.if..else niestandardowy znacznik szablonu

Co mam teraz jest (pseudokod):

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

('check_permission' to mój zwyczaj szablon).

Templatetag pobiera użytkownika, uprawnienie i instancję obiektu i zwraca załączony kod HTML (formularz). To obecnie działa dobrze.

Co chciałbym jednak zrobić, jest coś takiego jak:

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

Czytałem o the assignment tag, ale mój strach jest, że ja zanieczyszczają kontekstowe przestrzeni zmiennych z tego (czyli mogę nadpisać poprzednie zmienne kontekstu uprawnień). Innymi słowy, ponieważ zmienne kontekstowe są definiowane na różnych poziomach (widok, oprogramowanie warstwy pośredniej w moim przypadku, a teraz ten znacznik szablonu przypisania), martwię się o łatwość konserwacji.

Odpowiedz

13

Możesz użyć filtrów szablonów wewnątrz instrukcji if. Więc można było przepisać tag jako filtr:

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

Należy pamiętać, że jest to trudne do przekazania wiele argumentów różnych typów do filtra, więc prawdopodobnie będziesz chciał korzystać z jednego filtra za zgodą powyżej Użyłem check_can_edit.

+0

Dzięki, filtry rzeczywiście mogą być opcją. Przewiduję jednak różne uprawnienia (nie tylko podstawowy CRUD na instancję, ale niektóre bardzo konkretne), co oznacza, że ​​musiałbym utworzyć równą ilość niestandardowych filtrów szablonów. Być może powinienem jednak ponownie przemyśleć mój model uprawnień niestandardowych. Jeśli powiesz, że przekazanie wielu argumentów do filtra jest trudne, masz na myśli, że jest to możliwe? Myślałem, że tak nie jest, więc czy mógłbyś to trochę wyjaśnić? – LaundroMat

+1

Aktualizacja dla przyszłych użytkowników: Myślę, że spróbuję rozwiązać to za pomocą przykutych filtrów (np. '{{Request.user | has_permission:" entries.entry.can_edit, "| has_permission_on: article}}'. Niestandardowy filtr szablonu has_permission zwraca użytkownika i wymagane uprawnienie, has_permission_on następnie pobiera te wartości, sprawdza je względem zmiennej artykułu i zwraca True lub False. – LaundroMat

12

Z pewnością możesz to zrobić, jeśli chcesz napisać więcej linii kodu Pythona, aby poprawić czytelność szablonu! :)

Musisz sam przeanalizować treść znacznika, nawet parametry, które podejmuje, a następnie je rozwiązać, jeśli chcesz używać zmiennych na nich.

Znacznik realizowany poniżej mogą być używane tak:

{% load mytag %} 
{% mytag True %}Hi{% else %}Hey{% endmytag %} Bro 

Albo ze zmienną:

{% mytag myobject.myflag %}Hi{% else %}Hey{% endmytag %} Bro 

Więc oto sposób w jaki to zrobił:

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) 

I to jest to. HTH.

+0

prawdziwa odpowiedź tutaj – snakesNbronies