django用户认证系统——注销和页面跳转5
当用户想切换登录账号,或者想退出登录状态时,这时候就需要注销已登录的账号。现在我们来为网站添加注销登录的功能,这个功能 Django 也已经为我们提供,我们只需做一点简单配置。
注销登录
注销登录的视图为 logout,我们简单修改一下 index.html 的代码,添加一个注销登录的按钮:
- templates/index.html
- {% if user.is_authenticated %}
- <p>你已登录,欢迎你:<a href="#">{{ user.username }}</a></p>
- <button class="btn btn-default"><a href="{% url 'logout' %}">注销登录</a></button>
- {% else %}
- <p>你还没有登录,请
- <button class="btn btn-default"><a href="{% url 'login' %}">登录</a></button>
- 或者
- <button class="btn btn-default"><a href="{% url 'users:register' %}">注册</a></button>
- </p>
- {% endif %}
如果你已经登陆,就会看到一个注销登录的按钮,点击该按钮就会跳转到注销登录已成功地页面。再一次访问首页,你将看到登录、注册按钮,说明你已经成功注销登录状态了。
页面跳转
我们之前在登录、注册和注销的过程中发现,登录成功后会跳转到一个 404 页面,注册成功后返回的是首页,而注销登录后跳转到了 Admin 后台的注销成功页面。对于一个网站来说,比较好的用户体验是登录、注册和注销后跳转回用户之前访问的页面。否则用户在你的网站东跳转西跳转好不容易找到了想看的内容,结果他已登录给他跳转回了首页,这会使用户非常愤怒(我在有些网站就遇到过)。接下来我们看看如何让登录、注册和注销后跳转回用户之前访问的页面。
登录和注销后返回当前页面
在登录和注销的视图函数中,Django 已经为我们处理了跳转回用户之前访问页面的流程。其实现的原理是,在登录和注销的流程中,始终传递一个 next 参数记录用户之前访问页面的 URL。因此,我们需要做的就是在用户访问登录或者注销的页面时,在 URL 中传递一个 next 参数给视图函数,具体做法如下:
- templates/index.html
- <button class="btn btn-default">
- <a href="{% url 'logout' %}?next={{ request.path }}">注销登录</a>
- </button>
- <button class="btn btn-default">
- <a href="{% url 'login' %}?next={{ request.path }}">登录</a>
- </button>
可以看到,我们在登录和注销的 URL 后加了 next 参数,其值为 {{ request.path }}。request.path 是用户当前访问页面的 URL。在 URL 中传递参数的方法就是在要传递的参数前加一个 ?然后写上传递的参数名和参数值,用等号链接。关于在 URL 中传递参数具体请 HTTP 的相关协议。
为了在整个登录流程中记录 next 的值,还需要在登录表单中增加一个表单控件,用于传递 next 值。
- registration/login.html
- <form class="form" action="{% url 'login' %}" method="post">
- ...
- <button type="submit" class="btn btn-primary btn-block">登录</button>
- <input type="hidden" name="next" value="{{ next }}"/>
- </form>
即在表单中增加了一个隐藏的 input 控件,其值为 {{ next }},即之前通过 URL 参数传递给登录视图函数的,然后登录视图函数又将该值传递给了 login.html 模板。这样在整个登录流程中,始终有一个记录着用户在登录前页面 URL 的变量 next 在视图和模板间来回传递,知道用户登录成功后再跳转回 next 记录的页面 URL。
现在你可以点击登录和注销的按钮来走一遍登录和注销流程,发现页面跳转已经符合我们的需求了。不过还由一点点小瑕疵,就是如果用户不是通过点击登录和注销按钮,而是直接在页面输入 URL 来访问相关页面话,那这个 next 就没有值,从而无法向之前那样跳转回用户之前访问的页面。比如用户想登录,他直接在浏览器的地址栏输入 /users/login/,由于在 URL 中没有传递 next,所以就无法记录用户登录前的页面 URL,那在登录成功后就无法将他带回登录前的页面了。当然这种情况是极为罕见的,很少有用户会记住你网站的 URL 地址,但如果真有这样的用户,我们就把他跳转回首页吧,因为没有任何办法记录他之前访问的页面。要想把用户跳转回首页,可以在 settings 中做如下设置:
- LOGOUT_REDIRECT_URL = '/'
- LOGIN_REDIRECT_URL = '/'
这样,整个登录和注销流程就形成了一个闭环。如果用户通过点击登录或者注销按钮登录和注销的话,在登录或者注销成功后就会被带回登录或者注销前的页面,否则将他带回网站首页。
注册后返回当前页面
类似的,我们也希望用户注册后返回注册前页面。不过由于注册视图函数是我们自己写的,之前的处理方式是用户注册成功后将其带回网站首页,因此需要修改一下注册视图函数:
- users/views.py
- def register(request):
- # 从 get 或者 post 请求中获取 next 参数值
- # get 请求中,next 通过 url 传递,即 /?next=value
- # post 请求中,next 通过表单传递,即 <input type="hidden" name="next" value="{{ next }}"/>
- redirect_to = request.POST.get('next', request.GET.get('next', ''))
- # 只有当请求为 POST 时,才表示用户提交了注册信息
- if request.method == 'POST':
- # request.POST 是一个类字典数据结构,记录了用户提交的注册信息
- # 这里提交的就是用户名(username)、密码(password)、确认密码、邮箱(email)
- # 用这些数据实例化一个用户注册表单
- form = RegisterForm(request.POST)
- # 验证数据的合法性
- if form.is_valid():
- # 如果提交数据合法,调用表单的 save 方法将用户数据保存到数据库
- form.save()
- if redirect_to:
- return redirect(redirect_to)
- else:
- return redirect('/')
- else:
- # 请求不是 POST,表明用户正在访问注册页面,展示一个空的注册表单给用户
- form = RegisterForm()
- # 渲染模板
- # 如果用户正在访问注册页面,则渲染的是一个空的注册表单
- # 如果用户通过表单提交注册信息,但是数据验证不合法,则渲染的是一个带有错误信息的表单
- # 将记录用户注册前页面的 redirect_to 传给模板,以维持 next 参数在整个注册流程中的传递
- return render(request, 'users/register.html', context={'form': form, 'next': redirect_to})
逻辑非常简答,就是首先尝试从用户的 GET 或者 POST 请求中获取 next 参数值,即在注册成功后需要跳转的 URL,如果有值,注册成功后跳转到该 URL,否则跳转回首页。同是不要忘记将该值传给模板,以维持 next 参数在整个注册流程中的传递。
接下来修改模板,和登录模板的设置是一样的:
- registration/login.html
- <button class="btn btn-default">
- <a href="{% url 'users:register' %}?next={{ request.path }}">注册</a>
- </button>
- templates/users/register.html
- <form class="form" action="{% url 'users:register' %}" method="post">
- ...
- <button type="submit" class="btn btn-primary btn-block">注册</button>
- <input type="hidden" name="next" value="{{ next }}"/>
- </form>
注意:在注册视图函数中,对 next 的任意值我们都进行了跳转,这可能导致一些安全问题。正确的做法应该是在跳转前,对需要跳转的 URL 做安全性检查。不过这里只作为一个示例,在实际项目中请仔细考虑可能的安全后果,以及添加必要的安全性检查代码。
OK,如此修改以后,用户的登录、注册和注销流程的用户体验可以形成一个比较良好闭环了。接下来就来实现修改密码的功能。
django用户认证系统——注销和页面跳转5的更多相关文章
- django用户认证系统——修改密码6
再此之前我们已经完成了用户登录.注册.注销等功能,接下来让我们继续为用户提供修改密码的功能.该功能 Django 的 auth 应用也已经为我们提供,过程几乎和之前的登录功能完全一样. 编写修改密码模 ...
- django用户认证系统——重置密码7
当用户不小心忘记了密码时,网站需要提供让用户找回账户密码的功能.在示例项目中,我们将发送一封含有重置用户密码链接的邮件到用户注册时的邮箱,用户点击收到的链接就可以重置他的密码,下面是具体做法. 发送邮 ...
- django用户认证系统——拓展 User 模型
Django 用户认证系统提供了一个内置的 User 对象,用于记录用户的用户名,密码等个人信息.对于 Django 内置的 User 模型, 仅包含以下一些主要的属性: username,即用户名 ...
- “Django用户认证系统”学习资料收集
首推追梦人物——Django用户认证系统 待续……
- django用户认证系统——拓展 User 模型2
Django 用户认证系统提供了一个内置的 User 对象,用于记录用户的用户名,密码等个人信息.对于 Django 内置的 User 模型, 仅包含以下一些主要的属性: username,即用户名 ...
- django用户认证系统——基本设置1
网站提供登录.注册等用户认证功能是一个常见的需求.因此,Django 提供了一套功能完整的.灵活的.易于拓展的用户认证系统:django.contrib.auth.在本教程中,我将向你展示 auth ...
- django用户认证系统——登录4
用户已经能够在我们的网站注册了,注册就是为了登录,接下来我们为用户提供登录功能.和注册不同的是,Django 已经为我们写好了登录功能的全部代码,我们不必像之前处理注册流程那样费劲了.只需几分钟的简单 ...
- D django 用户认证系统
django认证系统包含三个部分:用户.权限和分组 安装 django项目默认启用了认证系统,如果不是使用django-admin.py创建项目的可以通过在settings配置文件里面的INSTALL ...
- Django用户认证系统(二)Web请求中的认证
在每个Web请求中都提供一个 request.user 属性来表示当前用户.如果当前用户未登录,则该属性为AnonymousUser的一个实例,反之,则是一个User实例. 你可以通过is_authe ...
随机推荐
- C8051F340之USB简介
背景 需求为实现一个键盘产品,于是将C8051F340作为主控制器.本篇记录C8051F340的USB控制器相关知识点,阅读本篇文章需要读者具有最基本的USB相关知识. 正文 C8051F340结构 ...
- struts 防止重复提交表单
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC &qu ...
- Java的内存机制(转)
0.参考资料: http://www.j2megame.org/index.php/content/view/2246/125.html 1.Java的内存机制 Java 把内存划分成两种:一种是栈内 ...
- LR 监控mysql
sapphire的个人空间 中介绍了LoadRunner监控Mysql和Appache进程占用cpu的方法 方法如下: 公司的新产品需要监控Mysql和Appache进程,求高手帮忙总算成功了. 服务 ...
- SSH登陆响应慢的问题
http://xiaobin.net/201112/ssh-login-quite-slow/ 同样的问题,有可能是两种情况: 第一种情况比较常见,也有很多资料提及到,就是在SSH登陆时服务器端会对客 ...
- mac 使用apache开启https功能,实现ios局域网内测(一)
笔者尝试了网上各种办法最后还是找到了方法解决了一系列局域网内测的问题,随手做个笔记记录下,亲测可行. 一.先生成证书 1.进入apache web 的根目录处理证书命令 cd /Library/Web ...
- 【转】C#播放H264裸码流
原文地址:https://www.cnblogs.com/cangyue080180/p/5873351.html 要播放H264裸码流,可以分拆为以下三个工作: 1.解码H264裸码流获取YUV数据 ...
- java基础讲解02-----eclipse快捷方式(2017-04-12 23:47)
ctrl + shift+o 出去多余的引用包 ctrl+i 修改格式
- python \uxxxx转中文,Python列表中的字典 \uxxxx转中文,
import json a = [{u', u'roleFlag': 7}] print json.dumps(a).decode("unicode_escape") 输出结果是: ...
- Laravel 5 教程 - 文件上传
一.简介 Laravel 有很棒的文件系统抽象层,是基于 Frank de Jonge 的 Flysystem 扩展包. Laravel 集成的 Flysystem 提供了简单的接口,可以操作本地端空 ...