Mam kilku użytkowników, którzy mogą zobaczyć określony widok.
Aby umożliwić użytkownikom logowanie się i składanie skarg przy użyciu pliku 403 Forbidden
dla tych użytkowników, którzy nie widzą tego loginu, mogę użyć następujących (jak wyjaśniono tutaj):
@permission_required("polls.can_vote", raise_exception=True)
@login_required
def my_view(request):
...
To rzeczywiście działa zgodnie z oczekiwaniami. Ale wszystkie moje poglądy są poglądami klasowymi. Od Django 1.9 (wreszcie!) Istnieje kilka ładnych miksów do robienia rzeczy, które były możliwe tylko przez dekoratorów. Jednak...
class MyClassView(LoginRequiredMixin, PermissionRequiredMixin, TemplateView):
raise_exception = <???>
permission_required = "polls.can_vote"
template_name = "poll_vote.html"
to nie działa. Ponieważ raise_exception
flaga jest używana przez oba LoginRequiredMixin
i PermissionRequiredMixin
, Nie mogę go ustawić na nic.
- gdyby
raise_exception
jestTrue
, niezalogowany użytkownik otrzymuje plik403 Forbidden
(czego nie chcę). - gdyby
raise_exception
jestFalse
czyli użytkownik nie będzie mógł zobaczyć widok, zostanie przekierowany na stronę logowania, która, ponieważ użytkownik jest zalogowany, przekieruje ponownie na tę stronę. Tworzenie niecodziennej pętli przekierowań.
Oczywiście mógłbym zaimplementować własny mixin, który zachowuje się tak, jak się spodziewałem, ale czy jest na to sposób Django w samym widoku? (nie w urls.py
)
Odpowiedzi:
6 dla odpowiedzi № 1W wielu przypadkach oczekiwanym zachowaniem jest podniesienie 403 dla nieuwierzytelnionych użytkowników. Więc tak, potrzebujesz niestandardowego miksu:
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 dla odpowiedzi nr 2
Chciałem dodać komentarz, ale moja reputacja na to nie pozwala. A co z następującymi? Czuję, że poniższe informacje są bardziej czytelne?
Zaktualizowany po komentarzach
Moje rozumowanie jest takie: w zasadzie piszesz zmodyfikowany dispatch
od LoginRequiredMixin
i po prostu ustaw raise_exception = True
. PermissionRequiredMixin
będzie raise PermissionDenied
gdy nie są spełnione odpowiednie uprawnienia
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 dla odpowiedzi № 3
Najprostszym rozwiązaniem wydaje się być niestandardowy zestaw widoków. Coś w tym stylu:
class PermissionsMixin(PermissionRequiredMixin):
def handle_no_permission(self):
self.raise_exception = self.request.user.is_authenticated()
return super(PermissionsMixin, self).handle_no_permission()
Lub po prostu użyj PermissionRequiredMixin
jak zwykle i umieść to handle_no_premission
do każdego CBV.