bbs论坛登录相关功能(2)
昨天把注册功能页面做出来,接下来就是登录页面
登录功能:
1,用户账号,密码后台效验,错误信息在登录按钮右边显示
2、验证码,根据图片生成,点击图片刷新产生新的验证码
修改密码
注册
先把前端页面login.html页面编辑出来
{#login.html#}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1 class="text-center">登录页面</h1> {% csrf_token %} <div class="form-group"> <label for="id_username">用户名:</label> <input type="text" name="username" id="id_username" class="form-control"> </div> <div class="form-group"> <label for="id_password">密码:</label> <input type="password" name="password" id="id_password" class="form-control"> </div> <div class="form-group">
{#验证码这里一个输入框,一个图片#}
<label for="id_code">验证码:</label> <div class="row"> <div class="col-md-6"> <input type="text" name="code" id="id_code" class="form-control"> </div> <div class="col-md-6"> <img src="/static/img/default.png" alt="" width="280" height="30"> </div> </div> </div> <buttom class="btn btn-success" id="id_button">登录</buttom> </div> </div> </div> </body> </html>
前端效果:
前端web展示图片:
方式1:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">登录页面</h1>
{% csrf_token %}
<div class="form-group">
<label for="id_username">用户名:</label>
<input type="text" name="username" id="id_username" class="form-control">
</div>
<div class="form-group">
<label for="id_password">密码:</label>
<input type="password" name="password" id="id_password" class="form-control">
</div>
<div class="form-group">
<label for="id_code">验证码:</label>
<div class="row">
<div class="col-md-6">
<input type="text" name="code" id="id_code" class="form-control">
</div>
<div class="col-md-6">
<img src="/get_code/" alt="" width="280" height="30"> {#指定路径#}
</div>
</div>
</div>
<buttom class="btn btn-success" id="id_button">登录</buttom>
</div>
</div>
</div>
</body>
</html>
# 设置urls.py路径
url(r'^get_code/',views.get_code)
# 设置views.py视图中的get_code函数 def get_code(request): # 推导,打开本地文件图片以二进制数据发送 # 以2进制方式打开本地图片2.jpg,设置别名f with open(r'F:\老男孩Python7期\项目\bbs\register\avatar\2.jpg','rb') as f: # 读取图片数据赋值给变量data data =f.read() # return数据返回到前端 return HttpResponse(data)
方式2(使用模板pillow)
安装模块:
pip3 install pillow
设置视图:
from PIL import Image,ImageDraw,ImageFont # image用生成图片,imagedraw在图片上写字,imageFont字体样式 def get_code(request): # 推导方式2,动态生成图片,发送二进制数据 img_obj = Image.new('RGB',(280,30),'red') # 以文件方式保存下来 with open('demo.png','wb') as f: img_obj.save(f) # 再以二进制模式打开文件发送 with open('demo.png','rb') as f: data=f.read() return HttpResponse(data)
实现固定颜色显示,怎么才刷新页面产生新的颜色呢?
方式3:
实现图片刷新,和图片存放
{#前端 login.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">登录页面</h1>
{% csrf_token %}
<div class="form-group">
<label for="id_username">用户名:</label>
<input type="text" name="username" id="id_username" class="form-control">
</div>
<div class="form-group">
<label for="id_password">密码:</label>
<input type="password" name="password" id="id_password" class="form-control">
</div>
<div class="form-group">
<label for="id_code">验证码:</label>
<div class="row">
<div class="col-md-6">
<input type="text" name="code" id="id_code" class="form-control">
</div>
<div class="col-md-6">
<img src="/get_code/" alt="" width="280" height="30">
</div>
</div>
</div>
<buttom class="btn btn-success" id="id_button">登录</buttom>
</div>
</div>
</div>
</body>
</html>
from PIL import Image,ImageDraw,ImageFont import random # 能够保存数据,取的时候二进制返回 from io import BytesIO def get_random(): # 随机生成三位随机数 return random.randint(0,255),random.randint(0,255),random.randint(0,255) def get_code(request): # 推导3,图片颜色动态变化,图片存放不再依赖文件的形式 img_obj= Image.new('RGB',(289,30),get_random()) # 生成一个io对象 io_obj = BytesIO() # 将这个对象看作文件句柄 img_obj.save(io_obj,'png') # 将图片数据存入内存管理器中,必须要指定图片格式 return HttpResponse(io_obj.getvalue()) # 将保存在内存管理器中的数据以二进制读取出来
实现效果:前端页面刷新,验证码图片颜色变化
接下来在图片上显示验证码(数字)
前端保持不变,后端设置视图:
from PIL import Image, ImageDraw, ImageFont import random # 能够保存数据,取的时候二进制返回 from io import BytesIO # 随机生成rgb参数 def get_random(): # 随机生成三位随机数 return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) def get_code(request): # 最终版本,颜色变化,显示数字 img_obj = Image.new('RGB', (280, 30), get_random()) # 生成一个画笔对象 img_draw = ImageDraw.Draw(img_obj) # 画笔就可以应用在该图片上 # 生成一个字体对象 img_font = ImageFont.truetype('static/font/mo.ttf', 30) # 随机验证码:数字+小写字母+大写字母 code = '' # 定义一个变量存储最终验证码 for i in range(5): random_int = str(random.randint(0, 9)) random_lower = chr(random.randint(97, 122)) random_upper = chr(random.randint(65, 90)) temp_code = random.choice([random_int, random_upper, random_lower]) # 将产生的字一个一个写到图片上,(60,0)代表坐标x轴,y轴;temp_upper代表文本;img_font代表设置好的字体 img_draw.text((60+i*30, 0), temp_code, get_random(), img_font) # code记录,控制间距 code += temp_code print(code) # 将code存放到session表中 request.session['code'] = code io_obj = BytesIO() img_obj.save(io_obj, 'png') return HttpResponse(io_obj.getvalue())
实现页面刷新,验证码也跟着变化:
点击验证码颜色范围内,刷新新的验证码:
后端不需要设置新的代码,前端需要修改当前这个图片的路径:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1 class="text-center">登录页面</h1> {% csrf_token %} <div class="form-group"> <label for="id_username">用户名:</label> <input type="text" name="username" id="id_username" class="form-control"> </div> <div class="form-group"> <label for="id_password">密码:</label> <input type="password" name="password" id="id_password" class="form-control"> </div> <div class="form-group"> <label for="id_code">验证码:</label> <div class="row"> <div class="col-md-6"> <input type="text" name="code" id="id_code" class="form-control"> </div> <div class="col-md-6"> <img src="/get_code/" alt="" width="280" height="30" id="id_img"> </div> </div> </div> <buttom class="btn btn-success" id="id_button">登录</buttom> </div> </div> </div> <script> $('#id_img').click(function () { //获取原来路径 let oldPath = $(this).attr('src'); //修改图片的src属性 $(this).attr('src',oldPath +='?') }) </script> </body> </html>
前端数据以ajax方式传到后端,后端进行处理
//login.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1 class="text-center">登录页面</h1> {% csrf_token %} <div class="form-group"> <label for="id_username">用户名:</label> <input type="text" name="username" id="id_username" class="form-control"> </div> <div class="form-group"> <label for="id_password">密码:</label> <input type="password" name="password" id="id_password" class="form-control"> </div> <div class="form-group"> <label for="id_code">验证码:</label> <div class="row"> <div class="col-md-6"> <input type="text" name="code" id="id_code" class="form-control"> </div> <div class="col-md-6"> <img src="/get_code/" alt="" width="280" height="30" id="id_img"> </div> </div> </div> <buttom class="btn btn-success" id="id_button">登录</buttom> <span class="errors" style="color: red" id="id_error"></span> </div> </div> </div> <script> $('#id_img').click(function () { //获取原来路径 let oldPath = $(this).attr('src'); //修改图片的src属性 $(this).attr('src',oldPath +='?') }) //发送数据 $('#id_button').click(function () { $.ajax({ url:'', type:'post', data:{ 'username':$('#id_username').val(), 'password':$('#id_password').val(), 'code':$('#id_code').val(), 'csrfmiddlewaretoken':'{{ csrf_token }}', }, success:function (data) { if (data.code == 100){ location.href = data.url } else{ $('#id_error').html(data.msg) } } }) }) </script> </body> </html>
from django.contrib import auth
# 登录模块 def login(request): back_dic = {'code':100,'msg':''} if request.method =='POST': username=request.POST.get('username') password=request.POST.get('password') code=request.POST.get('code') # 先效验验证码,忽略大小写 if request.session.get('code').upper() == code.upper(): user_obj = auth.authenticate(username=username,password=password) if user_obj: # 登陆成功,记录当前状态 auth.login(request,user_obj) back_dic['msg']='登陆成功' back_dic['url']='/home/' else: back_dic['code']=102 back_dic['msg']='用户或者密码错误' else: back_dic['code']=103 back_dic['msg']='验证码不正确' return JsonResponse(back_dic) return render(request, 'login.html')
首页(home)
# views.py def home(request): return render(request, 'home.html')
//home.html 用户登录成功、事变都默认跳转到home页面,用户登录时导航栏显示当前用户,用户密码修改和退出;用户未登录的时候显示的是登录和注册
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主页</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">BBS</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">文章 <span class="sr-only">(current)</span></a></li> <li><a href="#">随笔</a></li> </ul> <ul class="nav navbar-nav navbar-right"> {% if request.user.is_authenticated %} //使用auth判断用户是否登录 <li><a href="#">{{ request.user.username }}</a></li> //显示当前登录用户 <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">更多操作 <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="/set_password/">修改密码</a></li> <li><a href="#">修改头像</a></li> <li role="separator" class="divider"></li> <li><a href="/logout/">注销</a></li> </ul> </li> {% else %} <li><a href="/register/">注册</a></li> <li><a href="/login/">登录</a></li> {% endif %} </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> </body> </html>
实现效果(登录状态):
未登录状态:
退出功能:
# views.py
# auth.logout退出后会自动清楚session def logout(request): auth.logout(request) return redirect('/home/') # 退出后自动跳转到home页面
修改密码:
// set_password.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改密码</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1 class="text-center">修改密码页面</h1> <form action="" method="post"> {% csrf_token %} <div class="form-group"> <label for="id_username">用户名:</label>
{#request.user.username获取用户username的值,disabled禁用当前所在的栏 #}
<input type="text" name="username" id="id_username" value="{{ request.user.username }}" class="form-control" disabled> </div> <div class="form-group"> <label for="id_old_password">旧密码:</label> <input type="password" name="old_password" id="id_old_password" class="form-control"> </div> <div class="form-group"> <label for="id_password">输入密码:</label> <input type="password" name="password" id="id_password" class="form-control"> </div> <div class="form-group"> <label for="id_new_password">再次输入密码:</label> <input type="password" name="new_password" id="id_new_password" class="form-control"> </div> <button class="btn btn-success" id="id_button">确定修改</button>
{#errors.id_button从后端获取键是id_button的值打印出来,style=“color:red”打印出来的字符显示红色#}
<span style="color: red">{{ errors.id_button }}</span> </form> </div> </div> </div> </body> </html>
# 修改密码 def set_password(request): # errors={'old_password':'','password':'','new_password':''} errors={'id_button':''} #定义变量errors的键值,默认为空 if request.method == 'POST': old_password = request.POST.get('old_password') password = request.POST.get('password') new_password = request.POST.get('new_password') # print(old_password,password,new_password) # 从数据库中判断密码是否正确,前端明文会自动加密和后端对象的字段做对比 res= request.user.check_password(old_password) # 判断原密码是否正确 if res: if password == new_password: request.user.set_password(new_password) request.user.save() return redirect('/login/') else: errors['id_button']='输入的密码不一致' else: errors['id_button']='原密码输入不正确'return render(request, 'set_password.html',locals()) # locals()把前面定义的errors变量传递到前端
原密码不正确:
输入的密码和二次输入的密码不一致