Для своего сайта я создал абстрактную модель, которая реализует разрешения на чтение на уровне модели.Эта часть системы завершена и работает правильно.Один из методов, которые предоставляет разрешенная модель, - это is_safe(user)
, который может вручную проверить, разрешено ли пользователю просматривать эту модель или нет.
Я хотел бы добавить метод с эффектом * 1004.* который может быть вызван на любом экземпляре модели, и вместо возврата логического значения, такого как is_safe
, он сначала проверит, может ли модель быть просмотрена или нет, а в случае False он перенаправит пользователя либо настраницу входа, если они еще не вошли или возвращают ошибку 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)