2016-04-26 8 views
1

sagen, dass ich eine Ansicht, die mit dem user_passes_test Dekorateur eingerichtet wurde: es zu einer URL bisIn Django Vorlage: Überprüfen Sie, ob die Benutzerberechtigung Ansicht nach Name angegeben zuzugreifen

# myapp/views.py 
from django.views.generic import TemplateView 
from django.contrib.auth.decorators import user_passes_test 

def has_perm1_or_perm2(user): 
    return user.has_perm('myapp.perm1') or user.has_perm('myapp.perm2') 

@user_passes_test(has_perm1_or_perm2) 
class MyView(TemplateView): 
    # my view code goes here 

und ich Haken wie folgt:

# myapp/urls.py 
from django.conf.urls import url 
from . import views 

urlpatterns = [ 
    ..., 
    url(r'^myview$', views.MyView.as_view(), name='myview'), 
    ... 
] 

Wenn ich einen Link zu dieser Ansicht in einer Vorlage setzen will, würde es ungefähr so ​​aussehen:

<a href="{% url 'myapp:myview' %}">Check out my view!</a> 

Aber ich möchte in der Lage sein, einige Kontrolle in die Vorlage zu setzen, so dass das oben genannte nur angezeigt wird, wenn der aktuell angemeldete Benutzer von der für die Ansicht angegebenen Funktion user_passes_test genehmigt werden würde.

I.e. Ich möchte meine Vorlage wie folgt aussehen lassen:

{% if check_user_has_view_permission request.user 'myapp:myview' %} 
<a href="{% url 'myapp:myview' %}">Check out my view!</a> 
{% else %} 
Nothing to see here... 
{% endif %} 

Wie kann ich das erreichen?

Danke!

+0

Beachten Sie, dass der 'user_passes_test'-Dekorator für prozedurale Ansichten vorgesehen ist. Für klassenbasierte Ansichten müssen Sie [a mixin] (https://docs.djangoproject.com/en/1.9/topics/auth/default/#django.contrib.auth.mixins.UserPassesTestMixin) verwenden. – solarissmoke

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, einen Kommentar abzugeben. Ich hatte gedacht, dass es in der Vergangenheit möglich war, klassenbasierte Ansichten zu dekorieren. Ist das eine neue Sache in 1.9, dass Sie Mixins für CBVs verwenden müssen? Oder ist es nur Erlaubnis bezogene Dekorateure auf CBV? Oder ist das nur zu empfehlen, aber der Decorator-Ansatz funktioniert noch? – 8one6

+0

Decorators funktionieren nicht AFAIK. Vor Django 1.9 musste man eigene Mixins schreiben oder die "Dispatch" -Methode der Ansicht dekorieren. – solarissmoke

Antwort

1

Sie können eine custom template filter schreiben, die dies tun wird:

# myapp/templatetags/my_app_tags.py (probably need a better name...) 
from django import template 
from myapp.views import has_perm1_or_perm2 

register = template.Library() 

@register.filter 
user_has_special_perms(user): 
    return has_perm1_or_perm2(user) 

Dann in Ihrer Vorlage:

{% load my_app_tags %} 

{% if request.user|user_has_special_perms %} 
<a href="{% url 'myapp:myview' %}">Check out my view!</a> 
{% else %} 
Nothing to see here... 
{% endif %} 

Alternativ können Sie die einzelnen Berechtigungen überprüfen direkt wie folgt:

{% if perms.myapp.perm1 and perms.myapp.perm2 %} 

(offensichtlich ist dies weniger DRY).

EDIT - wie kann dies generischer gemacht werden?

Um dies generischer zu machen, könnten Sie so etwas tun. Zuerst eine Art Abbildung von Ansichten zu Berechtigungen erstellen, zB ,:

# myapp/views.py 
VIEW_PERMISSIONS = { 
    'MyView': has_perm1_or_perm2, 
    # etc for other views 
} 

dann die Vorlage Filter ändern wie folgt:

from myapp.views import VIEW_PERMISSIONS 

@register.filter 
user_has_special_perms(user, view_class): 
    perm_func = VIEW_PERMISSIONS.get(view_class, None) 
    if perm_func is not None: 
     return perm_func(user) 
    return false 

Und dann in der Vorlage:

{% if request.user|user_has_special_perms:"MyView" %} 

I Ich bin sicher, dass es möglich ist, dies zu erreichen, ohne eine explizite Abbildung durch VIEW_PERMISSIONS zu benötigen, indem ich irgendeine Art von Introspektion für die View-Klasse selbst verwende.

+0

Dies ist ein vernünftiger Anfang, aber es ist nicht so allgemein, wie ich es in seiner aktuellen Präsentation möchte. Insbesondere in meiner realen Anwendung werde ich Dutzende von Ansichtsfunktionen haben, von denen jede eine (potentiell) maßgeschneiderte Benutzerautorisierungs-Prüffunktion haben wird. (Ansicht 1 könnte "perma oder permb" sein ... Ansicht 2 könnte "perma und permc" usw. sein) Es ist daher wichtig, dass die Lösung nicht den manuellen Schritt des Erzeugens eines Filters für jede Benutzer-Erlaubnisprüfungsfunktion erfordert. ..das Tag muss basierend auf seinem URL-Namen automatisch herausfinden, welche Funktion für eine bestimmte Ansicht gilt. Möglich? – 8one6

+0

Ich habe bearbeitet, um zu antworten, um einen möglichen Ansatz zu geben, es allgemeiner zu machen. Im Idealfall müssen Sie die Klasse selbst inspizieren. – solarissmoke

+0

Ich lese diese Antwort (http://stackoverflow.com/questions/10966493/find-the-required-permissions-of-django-urls-without-calling-them) im Detail, um zu sehen, ob ich diesen Ansatz nutzen kann . Insbesondere sieht es so aus, als ob der Autor dort eine auf den neuesten Stand gebrachte Version des Core-Performers für die Rechteprüfung vorschlägt. Insbesondere bevor die Dekoration erfolgt, fügt sie die Validierungsfunktion selbst als ein Attribut an die Ansichtsfunktion an. Dies sollte es ermöglichen, die Validierungsfunktion später wieder aufzurufen. – 8one6