/ / Können PermissionRequiredMixin und LoginRequiredMixin kombiniert werden? - Django, Django-1.9

Können PermissionRequiredMixin und LoginRequiredMixin kombiniert werden? - Django, Django-1.9

Ich habe einige Benutzer, die eine bestimmte Ansicht sehen dürfen.

Um es Nutzern zu ermöglichen, sich einzuloggen und sich mit einem zu beschweren 403 Forbidden Für diejenigen Benutzer, die diese Anmeldung nicht sehen können, kann ich Folgendes verwenden (wie erklärt Hier):

@permission_required("polls.can_vote", raise_exception=True)
@login_required
def my_view(request):
...

Dies funktioniert in der Tat wie erwartet. Aber alle meine Ansichten sind klassenbasierte Ansichten. Seit Django 1.9 (endlich!) Gibt es eine ganze Reihe hübscher Mixins, um Dinge zu tun, die nur durch die Dekorateure möglich waren. Jedoch...

class MyClassView(LoginRequiredMixin, PermissionRequiredMixin, TemplateView):
raise_exception = <???>
permission_required = "polls.can_vote"
template_name = "poll_vote.html"

Das funktioniert nicht. Weil das raise_exception Flag wird von beiden verwendet LoginRequiredMixin und PermissionRequiredMixinIch kann nichts einstellen.

  • ob raise_exception ist TrueEin Benutzer, der nicht angemeldet ist, erhält eine 403 Forbidden (was ich nicht will).
  • ob raise_exception ist False, ein Benutzer, der ist nicht erlaubt, die Ansicht zu sehen, wird auf die Anmeldeseite umgeleitet, die, weil der Benutzer eingeloggt ist, erneut auf die Seite umleitet. Erstellen einer Umleitungsschleife, die nicht ganz so schick ist.

Natürlich könnte ich mein eigenes Mixin implementieren, das sich erwartungsgemäß verhält, aber gibt es irgendeinen Django-Weg, dies in der Ansicht selbst zu tun? (nicht in der urls.py)

Antworten:

6 für die Antwort № 1

In vielen Fällen ist die Erhöhung von 403 für nicht authentifizierte Benutzer das erwartete Verhalten. Also ja, du brauchst eine benutzerdefinierte Mischung:

class LoggedInPermissionsMixin(PermissionRequiredMixin):
def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_authenticated():
return redirect_to_login(self.request.get_full_path(),
self.get_login_url(), self.get_redirect_field_name())
if not self.has_permission():
# We could also use "return self.handle_no_permission()" here
raise PermissionDenied(self.get_permission_denied_message())
return super(LoggedInPermissionsMixin, self).dispatch(request, *args, **kwargs)

2 für die Antwort № 2

Ich wollte einen Kommentar hinzufügen, aber mein Ruf erlaubt es nicht. Wie wäre es mit dem Folgenden? Ich fühle das unten lesbare ist?

Nach Kommentaren aktualisiert

Mein Argument ist: Du schreibst grundsätzlich modifiziert dispatch von LoginRequiredMixin und einfach eingestellt raise_exception = True. PermissionRequiredMixin werden raise PermissionDenied wenn die richtigen Berechtigungen nicht erfüllt sind

class LoggedInPermissionsMixin(PermissionRequiredMixin):
raise_exception = True

def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_authenticated():
return redirect_to_login(self.request.get_full_path(),
self.get_login_url(),
self.get_redirect_field_name())
return super(LoggedInPermissionsMixin, self).dispatch(request, *args, **kwargs)

0 für die Antwort № 3

Die einfachste Lösung scheint eine benutzerdefinierte Ansicht zu sein. So ähnlich:

class PermissionsMixin(PermissionRequiredMixin):
def handle_no_permission(self):
self.raise_exception = self.request.user.is_authenticated()
return super(PermissionsMixin, self).handle_no_permission()

Oder, einfach benutzen PermissionRequiredMixin wie immer und zieh das aus handle_no_premission zu jedem CBV.