Что является противоположностью @login required decorator для представлений Django?
Если я хочу убедиться, что представление указано как имеющее публичный доступ, существует ли декоратор, эквивалентный @public_access, который был бы противоположен @login_required и ясно дал бы понять, что представление должно быть общедоступным всегда?
Один из вариантов использования, который я имею в виду, - это автоматическое добавление "@csrf_exempt" ко всем общедоступным представлениям в дополнение к тому, чтобы в коде было ясно, что представление должно быть общедоступным.
5 ответов:
К сожалению, в настоящее время нет встроенной поддержки для этого в Django, что оставляет вас под угрозой раскрытия конфиденциальной информации, когда
@login_requiredслучайно забывается.Вот решение одного из моих проектов:
middleware/security.py:def public(function): """Decorator for public views that do not require authentication """ orig_func = function while isinstance(orig_func, partial): # if partial - use original function for authorization orig_func = orig_func.func orig_func.is_public_view = True return function def is_public(function): try: # cache is found return function.is_public_view except AttributeError: # cache is not found result = function.__module__.startswith('django.') and not function.__module__.startswith('django.views.generic') # Avoid modifying admin and other built-in views try: # try to recreate cache function.is_public_view = result except AttributeError: pass return result class NonpublicMiddleware(object): def process_view_check_logged(self, request, view_func, view_args, view_kwargs): return def process_view(self, request, view_func, view_args, view_kwargs): while isinstance(view_func, partial): # if partial - use original function for authorization view_func = view_func.func request.public = is_public(view_func) if not is_public(view_func): if request.user.is_authenticated(): # only extended checks are needed return self.process_view_check_logged(request, view_func, view_args, view_kwargs) return self.redirect_to_login(request.get_full_path()) # => login page def redirect_to_login(self, original_target, login_url=settings.LOGIN_URL): return HttpResponseRedirect("%s?%s=%s" % (login_url, REDIRECT_FIELD_NAME, urlquote(original_target)))
settings.py:MIDDLEWARE_CLASSES = ( #... 'middleware.security.NonpublicProfilefullMiddleware', #... )И, наконец, код вида:
from <projname>.middleware import publi @public def some_view(request): #... # Login required is added automatically def some_private_view(request): #...Кроме того, вы можете посмотреть на "автоматическое оформление всех видов проекта django" сообщение в блоге
Как упоминалось в предыдущем постере, по умолчанию вход не требуется.
Однако иногда полезно блокировать определенные представления от зарегистрированных пользователей - например, нет смысла для зарегистрированного пользователя иметь возможность использовать страницу регистрации сайта. В этом случае вы можете сделать что-то вроде этого, основываясь на существующем login_required decorator
from django.contrib.auth.decorators import user_passes_test from django.conf import settings LOGGED_IN_HOME = settings.LOGGED_IN_HOME def login_forbidden(function=None, redirect_field_name=None, redirect_to=LOGGED_IN_HOME): """ Decorator for views that checks that the user is NOT logged in, redirecting to the homepage if necessary. """ actual_decorator = user_passes_test( lambda u: not u.is_authenticated(), login_url=redirect_to, redirect_field_name=redirect_field_name ) if function: return actual_decorator(function) return actual_decorator