Django:从登录页面重定向登录的用户


71

我想设置我的站点,以便如果用户点击该/login页面并且他们已经登录,它将把他们重定向到主页。如果未登录,它将正常显示。由于登录代码内置在Django中,我该怎么做?

Answers:


83

我假设您当前正在使用内置的登录视图,

(r'^accounts/login/$', 'django.contrib.auth.views.login'),

或您网址中的类似内容。

您可以编写包含默认视图的登录视图。它将检查用户是否已经登录,如果已经登录则重定向,否则使用默认视图。

就像是:

from django.contrib.auth.views import login

def custom_login(request):
    if request.user.is_authenticated():
        return HttpResponseRedirect(...)
    else:
        return login(request)

当然可以相应地更改您的网址:

(r'^accounts/login/$', custom_login),

19
您应该custom_login使用第二个参数声明,**kwargs以便将您不需要的所有参数传递给内置login视图。
viam0Zah 2010年

16
为什么没有这种默认行为?我无法想象已经登录的用户应该看到登录页面的情况?
Timmy O'Mahony

2
如果一个已经登录的用户没有足够的权限访问某个视图,则可以LOGIN_URL由其user_passes_test(因此permission_required)装饰者重定向到该用户。
Anatoly Rr 2012年

如果这样使用,如何将{'template_name':} dict传递给django的登录视图?
MohitC'9

1
由于login已被删除,因此不再起作用。@rodolfojcj回答下面的作品。
达卡

62

Django 1.10方式

对于2016年8月发布的Django 1.10,在[1]中存在的基于函数的视图中redirect_authenticated_user添加了一个名为的新参数。login()django.contrib.auth

假设我们有一个Django应用程序,文件名为views.py,文件名为urls.py。该urls.py文件将包含一些Python代码,如下所示:

#
# Django 1.10 way
#
from django.contrib.auth import views as auth_views
from . import views as app_views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', auth_views.login, name='login',
        kwargs={'redirect_authenticated_user': True}),
    url(r'^dashboard/', app_views.Dashboard.as_view(), name='dashboard'),
    url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
]

在该文件中,urlpatterns变量定义内的相关部分如下,该部分使用已提及的redirect_authenticated_user参数和True值:

    url(r'^login/', auth_views.login, name='login',
        kwargs={'redirect_authenticated_user': True}),

请注意,该redirect_authenticated_user参数的默认值为False

Django 1.11方式

对于2017年4月发布的Django 1.11,LoginView基于类的视图取代了login()基于函数的视图[2],它为您提供了两种选择:

  • 使用前面描述的相同的Django 1.10方法,这是一件好事,因为您当前的代码将继续正常工作。如果您告诉Python解释器显示警告,例如,在控制台终端中运行python -Wd manage.py runserverDjango项目目录中的命令,然后使用网络浏览器进入登录页面,您将在同一控制台终端中看到如下警告消息:

/usr/local/lib/python3.6/site-packages/django/contrib/auth/views.py:54:RemovedInDjango21警告:login()视图已被基于类的LoginView()取代。

  • 使用new Django 1.11 way,这将使您的代码更现代,并与将来的Django版本兼容。使用此选项,前面给出的示例现在将类似于以下示例:

再次假设我们有一个Django应用程序,其文件名为views.py,另一个文件名为urls.py。该urls.py文件将包含一些Python代码,如下所示:

#
# Django 1.11 way
#
from django.contrib.auth import views as auth_views
from . import views as app_views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/',
        auth_views.LoginView.as_view(redirect_authenticated_user=True),
        name='login'),
    url(r'^dashboard/', app_views.Dashboard.as_view(), name='dashboard'),
    url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
]

在该文件中,urlpatterns变量定义中的相关部分如下,该部分再次使用已提及的redirect_authenticated_user参数和True值,但将其作为参数传递给类的as_view方法LoginView

    url(r'^login/',
        auth_views.LoginView.as_view(redirect_authenticated_user=False),
        name='login'),

请注意,此处的默认值redirect_authenticated_user也是False

参考文献


1
@Quique提供了一个与Django 2.x兼容的简洁解决方案stackoverflow.com/a/53764272/9177173
ohlr

我遵循此方法时遇到此错误。login()缺少1个必需的位置参数:“ user”。升级到Django 2.2时出现此错误。有什么原因如何清除它?
Venkatesh Gotimukul

25

Anonymous_required装饰器

对于基于类的视图

码:

from django.shortcuts import redirect

def anonymous_required(func):
    def as_view(request, *args, **kwargs):
        redirect_to = kwargs.get('next', settings.LOGIN_REDIRECT_URL )
        if request.user.is_authenticated():
            return redirect(redirect_to)
        response = func(request, *args, **kwargs)
        return response
    return as_view

用法:

url(r'^/?$',
   anonymous_required(auth_views.login),
),
url(r'^register/?$',
    anonymous_required(RegistrationView.as_view()),
    name='auth.views.register'
),
# Could be used to decorate the dispatch function of the view instead of the url

对于视图功能

来自http://blog.motane.lu/2010/01/06/django-anonymous_required-decorator/

码:

from django.http import HttpResponseRedirect

def anonymous_required( view_function, redirect_to = None ):
    return AnonymousRequired( view_function, redirect_to )

class AnonymousRequired( object ):
    def __init__( self, view_function, redirect_to ):
        if redirect_to is None:
            from django.conf import settings
            redirect_to = settings.LOGIN_REDIRECT_URL
        self.view_function = view_function
        self.redirect_to = redirect_to

    def __call__( self, request, *args, **kwargs ):
        if request.user is not None and request.user.is_authenticated():
            return HttpResponseRedirect( self.redirect_to )
        return self.view_function( request, *args, **kwargs )

用法:

@anonymous_required
def my_view( request ):
    return render_to_response( 'my-view.html' )

1
使用装饰器是最好的答案。这种逻辑只会使实际视图混乱。
凯文·斯通

此外,对于CBV,您最好将其编写为mixin和重载dispatch()。有关许多示例,请参见django-braces。
凯文·斯通

嘿,您的答案应该会得到更多投票。到目前为止,更好的答案和更通用的方法。
Aaron Lelevier 2014年

我遵循此方法时遇到此错误。login()缺少1个必需的位置参数:“ user”。有什么原因如何清除它?
Venkatesh Gotimukul

16

对于Django 2.x,在您的urls.py中:

from django.contrib.auth import views as auth_views
from django.urls import path

urlpatterns = [
    path('login/', auth_views.LoginView.as_view(redirect_authenticated_user=True), name='login'),
]

这与Django 2.x完美搭配。auth_urls的完整列表可以在github上找到:github.com/django/django/blob/master/django/contrib/auth/…–
ohlr

如果我有我的网址并使用django loginview,如何执行重定向,如下所示。urlpatterns = [url(r'^ $',LoginView.as_view(template_name ='landing.html'),name ='landing')]
Venkatesh Gotimukul

在Django 3中工作
Alejandro

11

如果用户已经登录,则在登录视图上方添加此装饰器以重定向到/ home

@user_passes_test(lambda user: not user.username, login_url='/home', redirect_field_name=None)

并且不要忘记导入装饰器

from django.contrib.auth.decorators import user_passes_test


我喜欢我的建议没有说明而被否决。我为这一发现感到特别自豪,因为它优雅,务实,而且是一体式的!
斯蒂芬

这是imo最优雅的解决方案。
Sandeep Raju Prabhakar 2015年

如果您没有使用django.contrib.auth提供的通用视图,
那就太好

1
user.is_anonymous()可能比测试用户名更好。
Tim Tisdall

1
我认为不赞成投票可能与以下事实有关:该功能专门用于将人们重定向登录页面。例如,它将当前URL编码为nextGET变量。
蒂姆·迪斯达尔

9

由于基于类的视图(CBV)呈上升趋势。仅当访问未经身份验证的用户的视图时,此方法将帮助您重定向到另一个URL。

在我的示例中,注册页面覆盖了该dispatch()方法。

class Signup(CreateView):
    template_name = 'sign-up.html'

    def dispatch(self, *args, **kwargs):
        if self.request.user.is_authenticated:
            return redirect('path/to/desired/url')
        return super().dispatch(*args, **kwargs)

干杯!


3

我知道这是一个非常老的问题,但是如果有人需要,我将添加我的技术:


myproject / myapp / views / misc.py

from django.contrib.auth.views import login as contrib_login, logout as contrib_logout
from django.shortcuts import redirect
from django.conf import settings


def login(request, **kwargs):
    if request.user.is_authenticated():
        return redirect(settings.LOGIN_REDIRECT_URL)
    else:
        return contrib_login(request, **kwargs)

logout = contrib_logout

myproject / myapp / urls.py

from django.conf.urls import patterns, url

urlpatterns = patterns('myapp.views.misc',
    url(r'^login/$', 'login', {'template_name': 'myapp/login.html'}, name='login'),
    url(r'^logout/$', 'logout', {'template_name': 'myapp/logout.html'}, name='logout'),
)
...

0

假设您已完成内置Django用户身份验证的设置(并使用装饰器),请将其添加到settings.py中:

LOGIN_REDIRECT_URL = '/welcome/'

注意:“ / welcome /”是主页的URL。由您决定如何替换它。


-1,当用户成功登录LOGIN_REDIRECT_URL仅用于
托马斯斯·齐林斯基

-7

您所要做的只是将“ root” URL设置为主页视图。由于首页视图已被限制用于登录用户,因此它将自动将匿名用户重定向到登录页面。

保留网址原样。并添加如下内容:

(r'^$', 'my_project.my_app.views.homepage'),

1
请仔细阅读操作说明。问题是如果已通过身份验证的用户如何从登录页面重定向登录的用户。内置login视图不涵盖这种情况。
viam0Zah 2010年

我建议的方法同样适用。他想要的只是让已登录的用户跳过登录页面。我的方法建议主页(根)是主页。由于主页受到登录限制,因此匿名用户将被重定向到登录页面。我以前使用过这种方法。不要把我的解决方案记下来,因为你不理解。
Luiz C.

2
它仍然不能解决问题。登录的用户仍然可以访问登录页面(通过键入url或其他方式)。
Gerardo Marset

“您听不懂”大声笑–您听不懂这个问题
JC Rocamonde
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.