实战之BBS(仿博客园写一个论坛)(二)登录页面,…
2019-05-08 07:31:11来源:博客园 阅读 ()
一.登录页面
1.效果展示:
2.技术点:
2.1验证码:验证码这个功能用了Image,ImageDraw,ImageFont,random,BytesIO模块和session
Image是新创建一个图片,ImageDraw相当于在这个图片上创建一个画笔,ImageFont指定字体的格式
random随机模块,BytesIO开辟一片字节类型的内存空间,session用于存储验证码,验证码的具体细节请看上篇博客
2.2登录验证:我们的注册的时候,用的是auth.create_user()方法,这种方法会让我们的密码被加密,在数据库中如下图所示:
所以说我们只能把从前端的获取的密码,经过同样的加密之后再和数据库中的数据进行比对
user=auth.authenticate(request,username=username,password=password)
如果user存在,登录成功,保持登录状态,否则返回错误信息,并对前端进行渲染
2.2.1登录成功:
首先用auth.login把user绑定,相当于session和cookie但是使用方法比这两个都简单,执行之后,不退出登录的情况下,request.user就是auth.login(request,user)里面的user
auth.login(request,user)
登录成功之后,给前端返回数据,首先在函数开头定义一个response_msg用于标识成功或失败,初始化:
respone_msg={'code':100,'msg':''}
当登录成功的时候,code不变,给response添加一个URL:
respone_msg['url']='/home'
当登录成功的时候,跳转到home页面。当然了这行代码也需要前端的配合,前端:
success:function (data) { if(data.code==100){ location.href=data.url }
2.2.2登录失败:
登录失败,response_msg['code']变为101(或者随意一个数,和成功区别开就好),msg变为失败的信息,比如是验证码出错还是账号密码错误
把返回的msg数据在前端进行渲染,显示出来,效果如下:
3.流程图:
4.具体代码:
后端代码:
from django.shortcuts import render,HttpResponse,redirect from app01 import myforms from app01 import models from django.http import JsonResponse # Create your views here. from PIL import Image,ImageDraw,ImageFont from io import BytesIO,StringIO from django.contrib import auth import random #随机数据 def r_num(number): if number==2: return random.randint(0,128),random.randint(0,128),random.randint(0,128) if number == 1: return random.randint(128, 255), random.randint(128, 255), random.randint(128, 255) #验证码函数 def yzm(request): yzm_img=Image.new("RGB",(260,40),r_num(1)) draw=ImageDraw.Draw(yzm_img) font=ImageFont.truetype('static/1.ttf',40) code='' for i in range(5): random_num=str(random.randint(0,9)) random_up=str(chr(random.randint(65,90))) random_low=str(chr(random.randint(97,122))) random_code=random.choice([random_num,random_up,random_low]) draw.text((20+40*i,-5),random_code,r_num(2),font) code+=random_code io_obj=BytesIO() yzm_img.save(io_obj,'png') request.session['code']=code return HttpResponse(io_obj.getvalue()) #登录函数 def login(request): respone_msg={'code':100,'msg':''} if request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') yzm=request.POST.get('yzm') if request.session.get('code').upper()==yzm.upper(): user=auth.authenticate(request,username=username,password=password) if user: auth.login(request,user) respone_msg['url']='/home' else: respone_msg['code']=101 respone_msg['msg']='用户名或密码错误' else: respone_msg['code']=102 respone_msg['msg']='验证码错误' return JsonResponse(respone_msg) return render(request,'login.html',locals())
前端:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <h1 class="text-center">登录页面</h1> <div class="row"> <form class="col-lg-offset-3 col-lg-6"> {% csrf_token %} <div class="form-group"> <label for="id_username">用户名</label> <input type="text" class="form-control" id="id_username" placeholder="用户名"> </div> <div class="form-group"> <label for="id_password">密码</label> <input type="password" class="form-control" id="id_password" placeholder="密码"> </div> <div class="form-group"> <label for="id_yzm">验证码</label> <input type="text" class="form-control" id="id_yzm" placeholder="验证码"> <div style="margin-top: 30px"><img src="/yzm/" alt="" id="img_yzm"></div> </div> <div><input type="button" id="button_id" value="登录" class="btn btn-primary"></div> <div> <span id="error" style="color: red"></span></div> </form> </div> </div> <script> $('#img_yzm').click(function () { var path2 = $(this).attr('src'); $(this).attr('src',path2+='?') }); $('#button_id').click(function () { $.ajax({ url:'', type:'post', data:{ 'username':$('#id_username').val(), 'password':$('#id_password').val(), 'yzm':$('#id_yzm').val(), 'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val() }, success:function (data) { if(data.code==100){ location.href=data.url } else { $('#error').html(data.msg) } } }) }) </script> </body> </html> 前端代码
二.首页的实现
1.效果展示:
,上图可以分为左右两边面板模块,中间文章展示模块,页面顶部导航栏模块,顶部导航栏模块分为登录状态和非登录状态
非登录状态:
登录状态:
2.实现步骤
2.1左右两边面板模块:
左右两边面板模块用bootstarp的栅格系统完成,左2,中8,右2,然后再去copy3个面板,完成
2.2中间数据的展示:
后端操作很简单,只需要获取文章表的所有数据发送给前端即可
article_list=models.Article.objects.all() return render(request,'home.html',locals())
前端代码,把后端发过来的数据,用for循环渲染
{% for article in article_list %} <div class="media"> <div class="media-left"> <a href="#"> <img class="media-object" data-src="holder.js/64x64" alt="64x64" src="/media/{{ article.blog.userinfo.avatar }}" data-holder-rendered="true" style="width: 64px; height: 64px;"> </a> </div> <div class="media-body"> <h4 class="media-heading"><a href="/{{ article.blog.userinfo.username }}/{{ article.id }}">{{ article.title }}</a></h4> {{ article.desc }} <div> <span>发布时间:{{ article.create_time }} 点赞数:{{ article.up_num }} 评论数:{{ article.comment_num}}</span> </div> </div> </div> {% endfor %}
2.3页面顶部导航栏
首先实现不同状态下的前端切换,后端是locals()传值,所有request也被传到了前端,那么就可以通过request.user判断用户是否登录
{% if request.user.is_authenticated %}
<li><a href="/{{ request.user.username }}/GL">{{ 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="/set_avatar">修改头像</a></li>
<li role="separator" class="divider"></li>
<li><a href="/logout">注销</a></li>
{% else %}
<li><a href="/login">登录</a></li>
<li><a href="/register">注册</a></li>
</ul>
</li>{% endif %}
2.3.1非登录状态下
非登录状态下,给两个a标签添加路径,
<li><a href="/login">登录</a></li> <li><a href="/register">注册</a></li>
2.3.2 登录状态下,有三个功能,修改密码,修改头像,注销
修改密码:首先在url文件中添加路径,在views中添加函数,为a标签加上路径,在templates创建一个修改密码页面
效果如上
修改密码要有原密码。原密码的是加密的,所以又需要一个函数request.user.check_password()
验证之后,进行两次新密码的比对,没有问题的话,进行保存,又又又要对密码进行加密,所以需要另外一个函数request.user.set_password(new_password),还有设置完之后别忘记保存request.user.save()
后端:
def set_password(request): respone_msg={'code':100,'msg':''} if request.method=="POST": password=request.POST.get('password') if request.user.check_password(password): new_password=request.POST.get('new_password') re_new_password=request.POST.get('re_new_password') if new_password==re_new_password: respone_msg['url']='/login' request.user.set_password(new_password) request.user.save() auth.logout(request) else: respone_msg['code']=101 respone_msg['msg']='两次密码不一致' else: respone_msg['code'] = 102 respone_msg['msg'] = '原密码不正确' return JsonResponse(respone_msg) return render(request,'set_password.html',locals())
前端:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <body> <div class="container"> <h1 class="text-center">修改密码</h1> <div class="row"> <form class="col-lg-offset-3 col-lg-6"> {% csrf_token %} <div class="form-group"> <label for="id_username">用户名</label> <input type="text" class="form-control" id="id_username" placeholder="用户名" value={{ request.user.username }} disabled> </div> <div class="form-group"> <label for="id_password">密码</label> <input type="password" class="form-control" id="id_password" placeholder="密码"> </div> <div class="form-group"> <label for="id_password2">新密码</label> <input type="password" class="form-control" id="id_password2" placeholder="密码"> </div> <div class="form-group"> <label for="id_password3">重复新密码</label> <input type="password" class="form-control" id="id_password3" placeholder="密码"> </div> <div><input type="button" id="button_id" value="修改" class="btn btn-primary"></div> <div> <span id="error" style="color: red"></span></div> </form> </div> </div> <script> $('#button_id').click(function () { $.ajax({ url:'', type:'post', data:{ 'password':$('#id_password').val(), 'new_password':$('#id_password2').val(), 're_new_password':$('#id_password3').val(), 'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val() }, success:function (data) { if(data.code==100){ location.href=data.url } else { $('#error').html(data.msg) } } }) }) </script> </body> </body> </html>
修改头像:
头像修改的原理和注册时是一样的,简单不多BB
def set_avatar(request): blog = request.user.blog username = request.user.username if request.method=="POST": file = request.FILES.get('myfile') user_obj = models.UserInfo.objects.get(blog=blog) user_obj.avatar = file user_obj.save() return JsonResponse({'url':'/home','code':'100'}) return render(request,'set_avatar.html',locals())
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-lg-6"> {% csrf_token %} <label for="file_id"> 头像 <img data-src="holder.js/140x140" class="img-rounded" alt="140x140" style="width: 140px; height: 140px;" src="/media/{{ request.user.avatar }}" data-holder-rendered="true" id="img_id"> </label> <input type="file" id="file_id" class="hidden"> <p><input type="button" id="button_id" value="修改"></p> </div> </div> </div> <script> $('#file_id').change(function () { var file = $(this)[0].files[0]; var read = new FileReader(); read.readAsDataURL(file); read.onload = function () { $('#img_id').attr('src', read.result) } }); $('#button_id').click(function () { var formdata=new FormData(); formdata.append('myfile',$('#file_id')[0].files[0]); formdata.append('csrfmiddlewaretoken',$("[name='csrfmiddlewaretoken']").val()); $.ajax({ url:"", type:'post', data:formdata, processData: false, contentType: false, success:function (data) { if(data.code==100){ location.href=data.url } } }) }) </script> </body> </html>
至于最后一个注销就简单了:
和auth.login相对应的函数,auth.logout
def logout(request): auth.logout(request) return redirect('/home')
首页完整代码:
后端:
#首页 def home(request): article_list=models.Article.objects.all() return render(request,'home.html',locals()) #注销 def logout(request): auth.logout(request) return redirect('/home') #修改密码 def set_password(request): respone_msg={'code':100,'msg':''} if request.method=="POST": password=request.POST.get('password') if request.user.check_password(password): new_password=request.POST.get('new_password') re_new_password=request.POST.get('re_new_password') if new_password==re_new_password: respone_msg['url']='/login' request.user.set_password(new_password) request.user.save() auth.logout(request) else: respone_msg['code']=101 respone_msg['msg']='两次密码不一致' else: respone_msg['code'] = 102 respone_msg['msg'] = '原密码不正确' return JsonResponse(respone_msg) return render(request,'set_password.html',locals()) #修改头像 def set_avatar(request): blog = request.user.blog username = request.user.username if request.method=="POST": file = request.FILES.get('myfile') user_obj = models.UserInfo.objects.get(blog=blog) user_obj.avatar = file user_obj.save() return JsonResponse({'url':'/home','code':'100'}) return render(request,'set_avatar.html',locals())
前端:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <nav class="navbar navbar-inverse"> <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="#">博客园</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"> </ul> <ul class="nav navbar-nav navbar-right"> {% if request.user.is_authenticated %} <li><a href="/{{ request.user.username }}/GL">{{ 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="/set_avatar">修改头像</a></li> <li role="separator" class="divider"></li> <li><a href="/logout">注销</a></li> {% else %} <li><a href="/login">登录</a></li> <li><a href="/register">注册</a></li> </ul> </li>{% endif %} </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <div class="container-fluid"> <div class="row"> <div class="col-md-2"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">广告位</h3> </div> <div class="panel-body"> 广告位招租 </div> <div class="panel-body"> 广告位招租 </div> </div> <div class="panel panel-danger"> <div class="panel-heading"> <h3 class="panel-title">广告位</h3> </div> <div class="panel-body"> 广告位招租 </div> <div class="panel-body"> 广告位招租 </div> </div> <div class="panel panel-success"> <div class="panel-heading"> <h3 class="panel-title">广告位</h3> </div> <div class="panel-body"> 广告位招租 </div> <div class="panel-body"> 广告位招租 </div> </div> </div> <div class="col-md-8"> {% for article in article_list %} <div class="media"> <div class="media-left"> <a href="#"> <img class="media-object" data-src="holder.js/64x64" alt="64x64" src="/media/{{ article.blog.userinfo.avatar }}" data-holder-rendered="true" style="width: 64px; height: 64px;"> </a> </div> <div class="media-body"> <h4 class="media-heading"><a href="/{{ article.blog.userinfo.username }}/{{ article.id }}">{{ article.title }}</a></h4> {{ article.desc }} <div> <span>发布时间:{{ article.create_time }} 点赞数:{{ article.up_num }} 评论数:{{ article.comment_num}}</span> </div> </div> </div> {% endfor %} </div> <div class="col-md-2"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">广告位</h3> </div> <div class="panel-body"> 广告位招租 </div> <div class="panel-body"> 广告位招租 </div> </div> <div class="panel panel-danger"> <div class="panel-heading"> <h3 class="panel-title">广告位</h3> </div> <div class="panel-body"> 广告位招租 </div> <div class="panel-body"> 广告位招租 </div> </div> <div class="panel panel-success"> <div class="panel-heading"> <h3 class="panel-title">广告位</h3> </div> <div class="panel-body"> 广告位招租 </div> <div class="panel-body"> 广告位招租 </div> </div> </div> </div> </div> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-lg-6"> {% csrf_token %} <label for="file_id"> 头像 <img data-src="holder.js/140x140" class="img-rounded" alt="140x140" style="width: 140px; height: 140px;" src="/media/{{ request.user.avatar }}" data-holder-rendered="true" id="img_id"> </label> <input type="file" id="file_id" class="hidden"> <p><input type="button" id="button_id" value="修改"></p> </div> </div> </div> <script> $('#file_id').change(function () { var file = $(this)[0].files[0]; var read = new FileReader(); read.readAsDataURL(file); read.onload = function () { $('#img_id').attr('src', read.result) } }); $('#button_id').click(function () { var formdata=new FormData(); formdata.append('myfile',$('#file_id')[0].files[0]); formdata.append('csrfmiddlewaretoken',$("[name='csrfmiddlewaretoken']").val()); $.ajax({ url:"", type:'post', data:formdata, processData: false, contentType: false, success:function (data) { if(data.code==100){ location.href=data.url } } }) }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <body> <div class="container"> <h1 class="text-center">修改密码</h1> <div class="row"> <form class="col-lg-offset-3 col-lg-6"> {% csrf_token %} <div class="form-group"> <label for="id_username">用户名</label> <input type="text" class="form-control" id="id_username" placeholder="用户名" value={{ request.user.username }} disabled> </div> <div class="form-group"> <label for="id_password">密码</label> <input type="password" class="form-control" id="id_password" placeholder="密码"> </div> <div class="form-group"> <label for="id_password2">新密码</label> <input type="password" class="form-control" id="id_password2" placeholder="密码"> </div> <div class="form-group"> <label for="id_password3">重复新密码</label> <input type="password" class="form-control" id="id_password3" placeholder="密码"> </div> <div><input type="button" id="button_id" value="修改" class="btn btn-primary"></div> <div> <span id="error" style="color: red"></span></div> </form> </div> </div> <script> $('#button_id').click(function () { $.ajax({ url:'', type:'post', data:{ 'password':$('#id_password').val(), 'new_password':$('#id_password2').val(), 're_new_password':$('#id_password3').val(), 'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val() }, success:function (data) { if(data.code==100){ location.href=data.url } else { $('#error').html(data.msg) } } }) }) </script> </body> </body> </html>
原文链接:https://www.cnblogs.com/98WDJ/p/10817840.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- python项目实战:实时博客项目 源码下载 2019-07-24
- BBS(仿博客园系统)项目04(文章详情页根评论、子评论的功 2019-07-24
- Python爬虫实战:下载喜马拉雅音频文件 2019-05-22
- 来到博客园的第一天 2019-05-22
- 【Python爬虫】爬了七天七夜,终于爬出了博客园粉丝数排行榜 2019-05-22
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash