Django建教育平台(七)--用户登录
2017-08-14 22:15
363 查看
上一节说明的index和login页面, 并不需要专门写views, 因为是使用系统自带的templateview
这一节说明用户登录功能, 因为不是使用系统自带的view, 需要自己写login信息输入后的view.
1. 写用户登录view
a. 写粗略的users/views
b. 修改urls文件
c. 在views中打断点
注意图中def login改成def user_login
d. Run菜单中按Debug
e. 浏览器访问http://127.0.0.1:8000/login/
f. 观察pycharm中断点情况
标蓝色的那一行即是现在运行所在行, 进入了GET的判断分支, 在下方debug窗口可以看到request是WSGIRequest对象.
点击debug窗口中request变量左侧的三角形, 展开request, 可以看到method和path这两者内容:
按F8将剩余代码运行完毕, 然后查看浏览器效果, 已经正常显示login页面.
g. 修改login.html中form action
在login.html中搜索"帐号登录"
修改标红色线处:
修改后:
h. 浏览器确认效果
点击立即登录按钮, 出现CSRF报错
在login.html中增加csrf_token
在浏览器中查看csrf_token的机制, 就是通过跟服务器确认一个随机生成的密钥, 防止恶意post给服务器.
第一步, 进入开发者工具模式.
第二步, 点击①所指的按钮
第三步, 点击②所指的"立即登录"
第四步, 查看③所指的位置, 就能看到django隐藏input的密钥
i. 验证用户身份, 登录
在users/views中设置断点
然后在浏览器输入之前注册的用户和密码, 按"立即登录
4000
".
pycharm中views断点标蓝色了.
在debug窗口中看到request变量, 展开该变量, 能找到里边的POST QueryDict.
展开POST QueryDict, 能看到里边的username, password键值信息, 跟我们刚在浏览器输入的是一样的.
现在就知道该如何取出POST中的内容了.
修改users/views代码
2. 登录状态的判断
没有登录跟登录之后, 首页的显示状态不同.
未登录是这个样子的, 提示用户登录或者注册.
登陆后, 应该是这样子的, 点击后还能弹出进入个人中心或者退出的按钮.
要实现这样的显示差异, 需要判断是否登录,并作出相应改变.
a. 在index.html中修改以下代码:
在login页面输入已注册的用户名和密码, 按立即登录, 跳转到index页面, index页面中已按照我们的设想显示.
b.非登录状态的验证
但是现在我们网站一直处于登录状态, 为了检查非登陆状态的页面, 我们先进入http://127.0.0.1:8000/xadmin/页面, 把当前用户注销, 然后再访问主页, 得到以下页面.
3. 设置邮箱登录
目前登录只能用用户名登录, 不能用邮箱登录.
在users/views中添加以下代码:
在settings中增加以下代码:
在installed_apps前面增加代码
然后尝试用邮箱登录, 成功了.
4. 设置登录错误提示
当输入登录帐号或密码错误时, 应该给出提示
a. 在users/views中修改代码:
b. 将msg信息传给login.html
在login.html中以下位置插入{{ msg }}
故意输入错误的用户名或密码, 按登录后出现了提示信息.
5. 用class重写login的view
a. 将users/views中user_login函数注释掉
b. 编写LoginView类
经过测试, LoginView类是可以正常实现之前user_login函数的功能的
c. 配置主页的登录链接
由于index.html中设置login页面的链接方式有两种, 一种是/login/, 一种是login.html, 目前url指匹配第一种.
修改urls的匹配设定
6. 用form来检查登录
当用户登录时输入一些不合法信息时, 希望能提前检出不合法性, 减少服务器访问负担, 并提醒用户正确输入.
a. 在users下新建forms.py文件, 输入代码
b. users/views中修改代码
c. 提取login_form中error信息
在if login_form is_valid(): 这句前打断点
在login页面故意不输入任何信息即点击登录
到断点位置, 按F6 step over, 查看debugger窗口, 把login_form对象展开, 把_errors这个Dict展开, 看到password和username信息.
d. 将error信息传递到login.html
红色边框提示
修改前:
修改后:
在浏览器查看效果:
当不输入用户名或密码时, 改输入框会变红色边框.
错误语言提示:
修改前:
修改后:
浏览器查看效果, 在不输入用户名和密码的时候, 点击登录.
7. session和cookie自动登录机制
为什么需要cookie? 因为http协议本身是一种无状态的协议, 客户端对服务器的每一次请求都是独立的, 请求之间没有联系. 各个客户端对服务器来说都是一样的, 服务器不认客户端.
为了让服务器区别对待不同的客户端, 认客户端, 服务器给客户端发"会员卡".
下图解读,
客户端A第一次给服务器发请求1;
服务器收到请求1, 发现客户端A是首次来访, 然后就给A发会员卡, 会员卡ID=1.
客户端A收到会员卡后就储存着, 当第二次给服务器发送请求2时, 带上会员卡.
服务器收到请求2, 发现会员卡时, 就给客户端A发送相对应的"会员服务套餐".
浏览器访问百度, 进入开发者工具模式
能看到Cookies是由Name和Value组成的, 类似字典.
同样, 访问本地网站主页时, 也能看到cookies
将用户名和密码在客户端与服务器之间传来传去是危险的, 因此, 服务器会根据客户端传来的cookies, 生成一个session id, 客户端和服务器传递这个session id就可以了.
cookies和session都是储存在本地的(session也存在服务器端), session就存在django数据库中.
在用户已登录的状态下,查看django_session表.
打开表格, 是可以看到session信息的.
用户名, 密码等信息经过加密, 以字符串的形式储存在session_data键中, 在过期时间之前访问.
expire_date即过期时间, 是可以在django中设定过多长时间失效.
注意, 第二条session_key跟浏览器中cookies信息是一致的.
这一节说明用户登录功能, 因为不是使用系统自带的view, 需要自己写login信息输入后的view.
1. 写用户登录view
a. 写粗略的users/views
from django.shortcuts import render def user_login(request): if request.method == "POST": pass elif request.method == "GET": return render(request, "login.html", {})
b. 修改urls文件
from users.views import user_login # 新增代码 urlpatterns = [ url(r'^xadmin/', xadmin.site.urls), url('^$', TemplateView.as_view(template_name="index.html"), name="index"), url('^login/$', user_login, name="login") # 将原来的login写法修改成这样 ]
c. 在views中打断点
注意图中def login改成def user_login
d. Run菜单中按Debug
e. 浏览器访问http://127.0.0.1:8000/login/
f. 观察pycharm中断点情况
标蓝色的那一行即是现在运行所在行, 进入了GET的判断分支, 在下方debug窗口可以看到request是WSGIRequest对象.
点击debug窗口中request变量左侧的三角形, 展开request, 可以看到method和path这两者内容:
按F8将剩余代码运行完毕, 然后查看浏览器效果, 已经正常显示login页面.
g. 修改login.html中form action
在login.html中搜索"帐号登录"
修改标红色线处:
修改后:
h. 浏览器确认效果
点击立即登录按钮, 出现CSRF报错
在login.html中增加csrf_token
在浏览器中查看csrf_token的机制, 就是通过跟服务器确认一个随机生成的密钥, 防止恶意post给服务器.
第一步, 进入开发者工具模式.
第二步, 点击①所指的按钮
第三步, 点击②所指的"立即登录"
第四步, 查看③所指的位置, 就能看到django隐藏input的密钥
i. 验证用户身份, 登录
在users/views中设置断点
然后在浏览器输入之前注册的用户和密码, 按"立即登录
4000
".
pycharm中views断点标蓝色了.
在debug窗口中看到request变量, 展开该变量, 能找到里边的POST QueryDict.
展开POST QueryDict, 能看到里边的username, password键值信息, 跟我们刚在浏览器输入的是一样的.
现在就知道该如何取出POST中的内容了.
修改users/views代码
from django.shortcuts import render from django.contrib.auth import authenticate, login # 新增代码 def user_login(request): if request.method == "POST": user_name = request.POST.get("username", "") # 新增, 根据刚才断点的分析结果, 用字典方法取出username的值 pass_word = request.POST.get("password", "") # 新增, 根据刚才断点的分析结果, 用字典方法取出password的值 user = authenticate(username=user_name, password=pass_word) # 新增, 利用django自带的authenticate方法来确认这个用户是否合法, 如果合法, 则user是一个非空对象. if user is not None: # 如果该用户合法, 则user非空. login(request, user) # django自带的login方法 return render(request, "index.html") # 登录成功后返回首页 elif request.method == "GET": return render(request, "login.html", {})
2. 登录状态的判断
没有登录跟登录之后, 首页的显示状态不同.
未登录是这个样子的, 提示用户登录或者注册.
登陆后, 应该是这样子的, 点击后还能弹出进入个人中心或者退出的按钮.
要实现这样的显示差异, 需要判断是否登录,并作出相应改变.
a. 在index.html中修改以下代码:
<section class="headerwrap "> <header> <div class=" header"> <div class="top"> <div class="wp"> <div class="fl"><p>服务电话:<b>33333333</b></p></div> <!--登录后跳转--> {% if request.user.is_authenticated %} <!判断用户是否通过认证> <div class="personal"> <dl class="user fr"> <dd>bobby<img class="down fr" src="/static/images/top_down.png"/></dd> <dt><img width="20" height="20" src="/static/media/image/2016/12/default_big_14.png"/></dt> </dl> <div class="userdetail"> <dl> <dt><img width="80" height="80" src="/static/media/image/2016/12/default_big_14.png"/></dt> <dd> <h2>django</h2> <p>bobby</p> </dd> </dl> <div class="btn"> <a class="personcenter fl" href="usercenter-info.html">进入个人中心</a> <a class="fr" href="/logout/">退出</a> </div> </div> </div> {% else %} <!若用户未通过认证, 则显示以下按钮> <a style="color:white" class="fr registerbtn" href="register.html">注册</a> <a style="color:white" class="fr loginbtn" href="login.html">登录</a> {% endif %} </div> </div> <div class="middle">
在login页面输入已注册的用户名和密码, 按立即登录, 跳转到index页面, index页面中已按照我们的设想显示.
b.非登录状态的验证
但是现在我们网站一直处于登录状态, 为了检查非登陆状态的页面, 我们先进入http://127.0.0.1:8000/xadmin/页面, 把当前用户注销, 然后再访问主页, 得到以下页面.
3. 设置邮箱登录
目前登录只能用用户名登录, 不能用邮箱登录.
在users/views中添加以下代码:
from django.contrib.auth.backends import ModelBackend from django.db.models import Q # Q可以帮助实现并集 from .models import UserProfile class CustomBackend(ModelBackend): def authenticate(self, username=None, password=None, **kwargs): try: user = UserProfile.objects.get(Q(username=username) | Q(email=username)) # 会用username或者email对传入的username进行匹配 if user.check_password(password): return user except Exception as e: return None
在settings中增加以下代码:
在installed_apps前面增加代码
AUTHENTICATION_BACKENDS = ( 'users.views.CustomBackend', # 逗号不要省 )
然后尝试用邮箱登录, 成功了.
4. 设置登录错误提示
当输入登录帐号或密码错误时, 应该给出提示
a. 在users/views中修改代码:
def user_login(request): if request.method == "POST": user_name = request.POST.get("username", "") pass_word = request.POST.get("password", "") user = authenticate(username=user_name, password=pass_word) if user is not None: login(request, user) return render(request, "index.html") else: return render(request, "login.html", {"msg": "用户名或密码错误!"}) # 新增 msg 错误提示信息 elif request.method == "GET": return render(request, "login.html", {})
b. 将msg信息传给login.html
在login.html中以下位置插入{{ msg }}
故意输入错误的用户名或密码, 按登录后出现了提示信息.
5. 用class重写login的view
a. 将users/views中user_login函数注释掉
# def user_login(request): # if request.method == "POST": # user_name = request.POST.get("username", "") # pass_word = request.POST.get("password", "") # user = authenticate(username=user_name, password=pass_word) # if user is not None: # login(request, user) # return render(request, "index.html") # else: # return render(request, "login.html", {"msg": "用户名或密码错误!"}) # elif request.method == "GET": # return render(request, "login.html", {})
b. 编写LoginView类
from django.views.generic.base import View # import View class LoginView(View): def get(self, request): # 重写View的GET方法 return render(request, "login.html", {}) # 将user_login函数的GET判断分支的代码拉过来. def post(self, request): # 重写View的POST方法 user_name = request.POST.get("username", "") # 将user_login函数的POST判断分支的代码拉过来. pass_word = request.POST.get("password", "") user = authenticate(username=user_name, password=pass_word) if user is not None: login(request, user) return render(request, "index.html") else: return render(request, "login.html", {"msg": "用户名或密码错误!"})
经过测试, LoginView类是可以正常实现之前user_login函数的功能的
c. 配置主页的登录链接
由于index.html中设置login页面的链接方式有两种, 一种是/login/, 一种是login.html, 目前url指匹配第一种.
修改urls的匹配设定
urlpatterns = [ url(r'^xadmin/', xadmin.site.urls), url('^$|^index.html$', TemplateView.as_view(template_name="index.html"), name="index"), # 正则表达式表示A,B两模式匹配其中之一的, 写成A|B url('^login/$|login.html$', LoginView.as_view(), name="login"), # 正则表达式表示A,B两模式匹配其中之一的, 写成A|B ]
6. 用form来检查登录
当用户登录时输入一些不合法信息时, 希望能提前检出不合法性, 减少服务器访问负担, 并提醒用户正确输入.
a. 在users下新建forms.py文件, 输入代码
__author__ = 'Elvan' __date__ = '2017/8/13 19:39' from django import forms class LoginForm(forms.Form): username = forms.CharField(required=True) # 将username设置为必填字段 password = forms.CharField(required=True, min_length=5) # 将password设置为必填字段, 且最短长度是5
b. users/views中修改代码
from .forms import LoginForm # 中间代码省略 class LoginView(View): def get(self, request): return render(request, "login.html", {}) def post(self, request): login_form = LoginForm(request.POST) # 实例化LoginForm类的对象, 需传入request.POST参数 if login_form.is_valid(): # 检查login_form是否出错, 没出错的才验证用户名和密码 user_name = request.POST.get("username", "") pass_word = request.POST.get("password", "") user = authenticate(username=user_name, password=pass_word) if user is not None: login(request, user) return render(request, "index.html") else: return render(request, "login.html", {"msg": "用户名或密码错误!"}) else: return render(request, "login.html", {"login_form":login_form}) # 如果login_form出错, 则返回login_from对象, 在前端进一步处理
c. 提取login_form中error信息
在if login_form is_valid(): 这句前打断点
在login页面故意不输入任何信息即点击登录
到断点位置, 按F6 step over, 查看debugger窗口, 把login_form对象展开, 把_errors这个Dict展开, 看到password和username信息.
d. 将error信息传递到login.html
红色边框提示
修改前:
<div class="form-group marb20 "> <label>用 户 名</label> <input name="username" id="account_l" type="text" placeholder="手机号/邮箱" /> </div> <div class="form-group marb8 "> <label>密 码</label> <input name="password" id="password_l" type="password" placeholder="请输入您的密码" /> </div>
修改后:
<div class="form-group marb20 {% if login_form.errors.username %}errorput{% endif %}"> <label>用 户 名</label> <input name="username" id="account_l" type="text" placeholder="手机号/邮箱" /> </div> <div class="form-group marb8 {% if login_form.errors.password %}errorput{% endif %}"> <label>密 码</label> <input name="password" id="password_l" type="password" placeholder="请输入您的密码" /> </div>
在浏览器查看效果:
当不输入用户名或密码时, 改输入框会变红色边框.
错误语言提示:
修改前:
<div class="error btns login-form-tips" id="jsLoginTips">{{ msg }}</div>
修改后:
<div class="error btns login-form-tips" id="jsLoginTips">{% for key, error in login_form.errors.items %}{{ error }}{% endfor %}{{ msg }}</div>
浏览器查看效果, 在不输入用户名和密码的时候, 点击登录.
7. session和cookie自动登录机制
为什么需要cookie? 因为http协议本身是一种无状态的协议, 客户端对服务器的每一次请求都是独立的, 请求之间没有联系. 各个客户端对服务器来说都是一样的, 服务器不认客户端.
为了让服务器区别对待不同的客户端, 认客户端, 服务器给客户端发"会员卡".
下图解读,
客户端A第一次给服务器发请求1;
服务器收到请求1, 发现客户端A是首次来访, 然后就给A发会员卡, 会员卡ID=1.
客户端A收到会员卡后就储存着, 当第二次给服务器发送请求2时, 带上会员卡.
服务器收到请求2, 发现会员卡时, 就给客户端A发送相对应的"会员服务套餐".
浏览器访问百度, 进入开发者工具模式
能看到Cookies是由Name和Value组成的, 类似字典.
同样, 访问本地网站主页时, 也能看到cookies
将用户名和密码在客户端与服务器之间传来传去是危险的, 因此, 服务器会根据客户端传来的cookies, 生成一个session id, 客户端和服务器传递这个session id就可以了.
cookies和session都是储存在本地的(session也存在服务器端), session就存在django数据库中.
在用户已登录的状态下,查看django_session表.
打开表格, 是可以看到session信息的.
用户名, 密码等信息经过加密, 以字符串的形式储存在session_data键中, 在过期时间之前访问.
expire_date即过期时间, 是可以在django中设定过多长时间失效.
注意, 第二条session_key跟浏览器中cookies信息是一致的.
相关文章推荐
- Django建教育平台(八)--用户注册
- 第三百七十六节,Django+Xadmin打造上线标准的在线教育平台—创建用户操作app,在models.py文件生成5张表,用户咨询表、课程评论表、用户收藏表、用户消息表、用户学习表
- 第三百七十三节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表、验证码表、轮播图表
- Django建教育平台(六)--首页和登录页面配置
- 第三百八十五节,Django+Xadmin打造上线标准的在线教育平台—登录功能实现,回填数据以及错误提示html
- 基于IMOOC强力django+杀手级xadmin 打造上线标准的在线教育平台课程的学习(10)——Operation models.py的设计
- 第三百九十九节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5安装mysql5.6
- 基于IMOOC强力django+杀手级xadmin 打造上线标准的在线教育平台课程的学习(13)——xadmin介绍
- 第四百零二节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署,uwsgi安装和启动,nginx的安装与启动,uwsgi与nginx的配置文件+虚拟主机配置
- Django-1.10支持中文用户注册登录
- 第三百七十五节,Django+Xadmin打造上线标准的在线教育平台—创建课程机构app,在models.py文件生成3张表,城市表、课程机构表、讲师表
- 第三百七十七节,Django+Xadmin打造上线标准的在线教育平台—apps目录建立,以及数据表生成
- 支付宝开发平台之第三方授权登录与获取用户信息
- Window上python开发--4.Django的用户登录模块User
- django实战--天天生鲜项目开发(用户注册-登录-用户中心)
- 利用Django中间件middleware解决用户未登录问题(转)
- 基于IMOOC强力django+杀手级xadmin 打造上线标准的在线教育平台课程的学习(8)——User models.py的设计
- 基于IMOOC强力django+杀手级xadmin 打造上线标准的在线教育平台课程的学习(11)——makemigrations
- Django2集成xadmin详解-5-获取登录用户信息并填充相应Model字段
- 使用django的用户帐号登录 openfire