Django 自动判断没有登录跳转到登录页

当系统登录时,会自动重定向到刚刚点击的页面

使用基于类的视图时,可以使用 LoginRequiredMixin 这个 LoginRequiredMixin 应该在继承列表中最左侧的位置。

那 LoginRequiredMixin 如何使用呢?

Django官网给的python代码如下:

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

这个是什么意思呢?

login_url = '/login/' 代表的是当没有登录时,会跳转到  '/login/' 这个地址

redirect_field_name = 'redirect_to' 代表的是,当登录成功时会跳转到 'redirect_to' 这个地址

如果每个视图都写login_url = '/login/' 是不是有太多的重复的代码呢?

如何只写一次对所以的视图都起作用呢?

那我们分析一下 LoginRequiredMixin 的源代码:

class AccessMixin:
    """
    Abstract CBV mixin that gives access mixins the same customizable
    functionality.
    """
    login_url = None
    permission_denied_message = ''
    raise_exception = False
    redirect_field_name = REDIRECT_FIELD_NAME

    def get_login_url(self):
        """
        Override this method to override the login_url attribute.
        """
        login_url = self.login_url or settings.LOGIN_URL
        if not login_url:
            raise ImproperlyConfigured(
                '{0} is missing the login_url attribute. Define {0}.login_url, settings.LOGIN_URL, or override '
                '{0}.get_login_url().'.format(self.__class__.__name__)
            )
        return str(login_url)

我们发现python中有这句代码 login_url = self.login_url or settings.LOGIN_URL

意思是说如果没有设置login_url 这个属性,那么可以使用 settings配置文件中的LOGIN_URL这个变量值。

发现这个规律,就很容易解决这个问题。

settings配置信息如下:

# 判断用户是否登录后,指定未登录用户重定向的地址
LOGIN_URL = '/login/'

当我们配置好了LOGIN_URL 之后

www.xinbiancheng.cn/login/?next=/info/

我们发现/info/这个地址是我们刚刚点击的地址

那next是从哪里来的呢?我们去看一下源代码:

REDIRECT_FIELD_NAME = 'next'

我们发现重定向的变量有默认的值是next

所以 redirect_field_name = 'redirect_to' 这句代码就可以不写了

只写一个配置文件,当登录成功时就可以跳转到/info/这个页面吗?目前还不呢?

还需要加上如下代码:

        # 先取出next
        next = request.GET.get('next')
        if next:
            # 重定向到next
            response = redirect(next)
        else:
            # 重定向到首页
            response = redirect(reverse('contents:index'))

完整python代码如下:

class LoginView(View):
    """用户登录"""

    def get(self, request):
        """提供用户登录页面"""
        return render(request, 'login.html')

    def post(self, request):
        """实现用户登录逻辑"""
        # 接收参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        remembered = request.POST.get('remembered')

        # 校验参数
        if not all([username, password]):
            return http.HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('请输入正确的用户名或手机号')

        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('密码最少8位,最长20位')

        # 认证用户:使用账号查询用户是否存在,如果用户存在,再校验密码是否正确
        user = authenticate(username=username, password=password)
        if user is None:
            return render(request, 'login.html', {'account_errmsg': '账号或密码错误'})

        # 状态保持
        login(request, user)
        # 使用remembered确定状态保持周期(实现记住登录)
        if remembered != 'on':
            # 没有记住登录:状态保持在浏览器会话结束后就销毁
            request.session.set_expiry(0) # 单位是秒
        else:
            # 记住登录:状态保持周期为两周:默认是两周
            request.session.set_expiry(None)

        # 响应结果
        # 先取出next
        next = request.GET.get('next')
        if next:
            # 重定向到next
            response = redirect(next)
        else:
            # 重定向到首页
            response = redirect(reverse('contents:index'))

        # 为了实现在首页的右上角展示用户名信息,我们需要将用户名缓存到cookie中
        # response.set_cookie('key', 'val', 'expiry')
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

        # 用户登录成功,合并cookie购物车到redis购物车
        response = merge_carts_cookies_redis(request=request, user=user, response=response)

        # 响应结果
        return response