Для моего сайта я создал абстрактную Модель, которая реализует полномочия чтения образцового уровня. Та часть системы завершается и работает правильно. Один из методов, которые представляет permissioned модель, is_safe(user)
который может вручную протестировать, если пользователю разрешают просмотреть ту модель или нет.
То, что я хотел бы сделать, добавляет метод к эффекту continue_if_safe
который можно назвать на любом образцовом экземпляре, и вместо того, чтобы возвратить булево значение как is_safe
это сначала протестировало бы, если модель может быть просмотрена или нет, то в случае Лжи, это перенаправило бы пользователя, или к странице входа в систему, если они не уже зарегистрированы или возвращают 403 ошибки, если они зарегистрированы.
Идеальное использование:
model = get_object_or_404(Model, slug=slug)
model.continue_if_safe(request.user)
# ... remainder of code to be run if it's safe down here ...
Я посмотрел на то, как get_object_or_404 работает, и он бросает Http404
ошибка, которая, кажется, имеет смысл. Однако проблема состоит в том, что, кажется, нет эквивалентного перенаправления или 403 ошибок. Что лучший способ состоит в том, чтобы пойти об этом?
(нерабочий) continue_if_safe метод:
def continue_if_safe(self, user):
if not self.is_safe(user):
if user.is_authenticated():
raise HttpResponseForbidden()
else:
raise HttpResponseRedirect('/account/')
return
Код для конечного решения, в случае, если другие "накопители" нуждаются в некоторой помощи с этим:
В абстрактной модели:
def continue_if_safe(self, user):
if not self.is_safe(user):
raise PermissionDenied()
return
Представления пойманы промежуточным программным обеспечением:
class PermissionDeniedToLoginMiddleware(object):
def process_exception(self, request, exception):
if type(exception) == PermissionDenied:
if not request.user.is_authenticated():
return HttpResponseRedirect('/account/?next=' + request.path)
return None
Использование в представлении (очень короткий и сладкий):
model = get_object_or_404(Model, slug=slug)
model.continue_if_safe(request.user)
Для запрещенной (403) ошибки вы можете поднять исключение PermissionDenied
(из django.core.exceptions
).
Что касается поведения перенаправления, нет встроенного способа справиться с этим так, как вы описали в своем вопросе. Вы можете написать пользовательское промежуточное ПО, которое будет ловить исключение и перенаправлять в process_exception
.
Вы хотите использовать для этого декораторы. Посмотрите пример login_required
. В основном декоратор позволит вам проверить безопасность, а затем вернуть HttpResponseRedirect ()
, если это небезопасно.
Ваш код будет выглядеть примерно так:
@safety_check:
def some_view(request):
#Do Stuff