Django, перенаправить всех неаутентифицированных пользователей на целевую страницу

У меня есть веб-сайт django с множеством URL-адресов и просмотров. Теперь я попросил перенаправить всех неаутентифицированных пользователей на определенную целевую страницу. Таким образом, все представления должны проверять user.is_authenticated() и возвращаться на новый набор целевых страниц.

Можно ли это сделать красиво, вместо того, чтобы столько возиться с моими views.py/urls.py?


person xpanta    schedule 14.01.2014    source источник
comment
django-stronghold (github.com/mgrouchy/django-stronghold) делает все ваши представления обязательными для входа дефолт   -  person RemcoGerlich    schedule 15.01.2014


Ответы (8)


Вы можете использовать промежуточное ПО.

Что-то вроде этого будет проверять аутентификацию пользователя при каждом запросе:

class AuthRequiredMiddleware(object):
    def process_request(self, request):
        if not request.user.is_authenticated():
            return HttpResponseRedirect(reverse('landing_page')) # or http response
        return None

Документы: process_request

Также не забудьте включить его в settings.py

MIDDLEWARE_CLASSES = (
    ...
    'path.to.your.AuthRequiredMiddleware',
)
person Dmit3Y    schedule 14.01.2014
comment
Этот ответ несколько устарел. Для текущих версий Django лучше всего увидеть ответ @AriG ниже. - person Craig S. Anderson; 29.11.2018
comment
Но это решение требует указания URL-адреса входа для каждого отдельного представления. ОП говорит, что он хочет, чтобы это происходило для всех неаутентифицированных запросов ко всем представлениям. - person c6754; 24.01.2020

Есть более простой способ сделать это, просто добавьте параметр «login_url» в @login_required, и если пользователь не авторизовался, он будет перенаправлен на страницу входа. Вы можете найти его здесь

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
    ...
person AriG    schedule 17.07.2017
comment
Элегантное решение идеально и работает как шарм. Добавили URL-адреса входа и выхода в мои URL-адреса входа/выхода, и они, в свою очередь, помогают с идеальным перенаправлением. Спасибо, что поделился. - person Doogle; 27.09.2018
comment
Это не может работать для класса? Я создал класс, который наследуется от Django LoginView CustomLoginView(LoginView) Однако у меня есть это сообщение об ошибке: path('login/', views.CustomLoginView.as_view(), name='login') - person Solal; 14.03.2019
comment
@Solal Используйте LoginRequiredMixin, например class someView(LoginRequiredMixin, CreateView): и т. д. В теле не забудьте добавить login_url для перенаправления страницы. - person user12379095; 28.07.2020
comment
Как это сделать для пользователей, не входящих в группу, если их группа не разрешает это. - person DerekPK; 18.07.2021

см. документы для требуется декоратор для входа

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...

другой вариант — добавить его в шаблоны urls.py, см. этот ответ

urlpatterns = patterns('',
    (r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
)
person Guy Gavriely    schedule 14.01.2014
comment
Это то, чего я хотел бы избежать. Добавление декораторов ко всем моим представлениям и изменение всех действий с URL-адресами. С другой стороны, я хочу перенаправить не на вход, а на другую страницу. С этой страницы, если пользователь хочет, может войти в систему, чтобы уйти. - person xpanta; 15.01.2014
comment
хотя это не решает вопрос ОП, оно все же дает хорошее решение. Я бы добавил, что ваш декоратор может иметь перенаправление; пример @login_required(login_url='/accounts/signin') - person adhg; 19.10.2018

Начиная с Django 1.10, пользовательские классы промежуточного ПО должны реализовывать синтаксис нового стиля. Вы можете использовать следующий класс, чтобы убедиться, что пользователь вошел в систему при попытке доступа к каким-либо представлениям.

from django.shortcuts import HttpResponseRedirect


class AuthRequiredMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = self.get_response(request)
        if not request.user.is_authenticated: # in Django > 3 this is a boolean
            return HttpResponseRedirect('login')
        
        # Code to be executed for each request/response after
        # the view is called.

        return response
person IVI    schedule 20.05.2017
comment
Я думаю, вам нужно переместить вызов self.get_response(request) так, чтобы он приходил после проверки request.user.is_authenticated() . Как это написано, неаутентифицированный запрос запустит код просмотра, который сгенерирует ответ, а затем проверка аутентификации заменит этот ответ перенаправлением на страницу входа. Любые обновления/удаления в коде представления в любом случае должны быть ограничены проверками разрешений, но, вероятно, лучше не рисковать. - person Grant McLean; 30.05.2018

Это можно сделать с помощью промежуточного программного обеспечения.

Я нашел действительно отличный djangosnippet, который делает именно то, о чем вы просите. Вы можете найти его здесь, и он выглядит так:

from django.http import HttpResponseRedirect
from django.conf import settings
from re import compile

EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
    EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS]

class LoginRequiredMiddleware:
    """
    Middleware that requires a user to be authenticated to view any page other
    than LOGIN_URL. Exemptions to this requirement can optionally be specified
    in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which
    you can copy from your urls.py).

    Requires authentication middleware and template context processors to be
    loaded. You'll get an error if they aren't.
    """
    def process_request(self, request):

        assert hasattr(request, 'user'), "The Login Required middleware\
 requires authentication middleware to be installed. Edit your\
 MIDDLEWARE_CLASSES setting to insert\
 'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't\
 work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes\
 'django.core.context_processors.auth'."

        if not request.user.is_authenticated():
            path = request.path_info.lstrip('/')
            if not any(m.match(path) for m in EXEMPT_URLS):
                return HttpResponseRedirect(settings.LOGIN_URL)

Все, что вам нужно сделать, это сохранить файл как middleware.py и включить класс в свой settings.py, т.е.

MIDDLEWARE_CLASSES += ('projectname.common.middleware.RequireLoginMiddleware',)

Вы также можете определить LOGIN_URL в settings.py, чтобы вы были перенаправлены на свою пользовательскую страницу входа. По умолчанию LOGIN_URL равно '/accounts/login/'.

person Martin Hallén    schedule 14.01.2014
comment
Для таких, как я, которые были сбиты с толку недавними изменениями, is_authenticated() больше не вызывается, теперь это просто логическая переменная, поэтому удалите () :) - person fantasitcalbeastly; 12.12.2019

Вы можете не указывать login_url, установив LOGIN_URL.

Поэтому в settings.py добавляем:

LOGIN_URL = '<some_url>'

И в вашем views.py аннотируйте соответствующие функции только @login_required:

@login_required
def some_view_function(request):

Если вам нужно перенаправить внутри функции просмотра, вы можете сделать это с помощью:

return redirect_to_login(request.get_full_path())
person Rok Strniša    schedule 01.11.2020

Может быть, слишком поздно, но в django 1.9+ это слишком просто. Django представил требуемый для входа миксин для универсального классы, и это отличный пример здесь от Уильям С. Винсент

просто на ваш взгляд добавьте LoginRequiredMixin в качестве родительского класса

from django.contrib.auth.mixins import LoginRequiredMixin

class BlogUpdateView(LoginRequiredMixin, UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body']

Также вы можете использовать декоратор login_required для запроса метода

person Alireza Saremi    schedule 15.02.2019

from django.contrib.auth.decorators import login_required

@login_required(login_url='/login/')

def home(request):
    return render(request, "home.html")

Это выглядит так: http://127.0.0.1:1235/login/?next=/home/

person Khairul2kha    schedule 16.08.2020