4.登陆功能
登陆页面初步搭建
<body> <div class="container-fluid"> <div class="row"> <div class="col-xs-8 col-xs-offset-2"> <h1 class="text-center">登陆</h1> <div class="form-group"> <label for="username">用户名</label> <input type="text" name="username" id="username" class="form-control"> </div> <div class="form-group"> <label for="password">密码</label> <input type="text" name="password" id="password" class="form-control"> </div> <div class="form-group"> <label for="">验证码</label> <div class="row"> <div class="col-xs-6"> <input type="text" name="code" id="id_code" class="form-control"> </div> <div class="col-xs-6"> {% load static %} <img src="{% static '/img/default.png' %}" alt="" width="610px" height="35px"> </div> </div> </div> <input type="button" class="btn btn-success" value="登陆"> </div> </div> </div> </body>
图片验证码
# img标签的src属性 1.图片路径 2.url 3.图片的二进制数据 # 我们计算机能够输出各式各样的字体样式,内部其实是对应者一个个(.ttf结尾)的文件 https://www.zhaozi.cn/ai/2019/fontlist.php?ph=1&classid=32&softsq=%E5%85%8D%E8%B4%B9%E5%95%86%E7%94%A8 # 图片相关模块 pip3 install pillow Image:生成图片 ImageDraw:能够在图片上乱涂乱画 ImageFont:控制字体样式 from PIL import Image,ImageDraw,ImageFont # 内存管理器模块 BytesIO:临时帮你存储数据 返回的时候数据是二进制 StringIO:临时帮你存储数据 返回的时候数据是字符串 from io import BytesIO,StringIO
需要将图片的src属性更改
from django.contrib import admin from django.urls import path,re_path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), # 登陆功能 re_path(r'^login/', views.login, name='login'), # 图片验证码相关操作 re_path(r'^get_code/', views.get_code, name='get_code') ]
def login(request): return render(request,'login.html') ''' 图片相关的模块 pip3 install pillow Image:能够帮你生成图片 ImageDraw:能够在图片上乱涂乱画 ImageFont:能够控制字体样式 ''' from PIL import Image,ImageDraw,ImageFont from io import BytesIO,StringIO ''' 内存管理模块 BytesIO:临时帮你存储数据,返回的时候数据是二进制 StringIO:临时帮你存储数据,返回的时候数据是字符串 ''' import random def get_random(): return random.randint(0,255),random.randint(0,255),random.randint(0,255) def get_code(request): # # 推导步骤1:直接获取后端现成的图片二进制数据发送给前端 # with open(r'static/img/111.png','rb') as f: # data = f.read() # return HttpResponse(data) # 推导步骤2:利用pillow模块动态产生图片 # img_obj = Image.new('RGB',(610,35),'green') # img_obj = Image.new('RGB',(610,35),get_random()) # # 先将图片对象保存起来 # with open('xxx.png','wb') as f: # img_obj.save(f,'png') # # 再将图片对象读取出来 # with open('xxx.png','rb') as f: # data = f.read() # print(data) # return HttpResponse(data) # 推导步骤3:文件存储繁琐IO效率低,借助于内存管理器 # img_obj = Image.new('RGB',(610,35),get_random()) # io_obj = BytesIO() # 生成一个内存管理对象,可以看成是文件句柄 # img_obj.save(io_obj,'png') # return HttpResponse(io_obj.getvalue()) # 从内存管理器中读取二进制的图片返回给前端 # 推导步骤4:些图片验证码 img_obj = Image.new('RGB',(610,35),get_random()) img_draw = ImageDraw.Draw(img_obj) # 产生一个画笔对象 img_font = ImageFont.truetype('static/font/111.ttf',30) # 字体样式 字体大小 # 随机验证码(五位数字的随机验证码,数字、小写字母、大写字母) code = '' for i in range(5): random_upper = chr(random.randint(65,90)) random_lower = chr(random.randint(97,122)) random_int = str(random.randint(0,9)) # 从上面三个里面随机选择一个 tmp = random.choice([random_upper,random_lower,random_int]) # 将产生的随机字符串写到图片上 ''' 为什么一个一个写而不是生成好之后再写 因为一个个写能够控制每个字体的间隙,而生成好之后再写的话,间隙就没法控制 ''' img_draw.text((i*100+100,-2),tmp,get_random(),img_font) # 拼接随机字符串 code += tmp print(code) # 随机验证码在登陆的视图函数里面需要用到,要对比,所以要找地方存起来并且其他视图函数也能拿到 request.session['code'] = code io_obj = BytesIO() img_obj.save(io_obj, 'png') return HttpResponse(io_obj.getvalue())
每次重新加载一次图片会在路由后面加上一个”?“
<body> <div class="container-fluid"> <div class="row"> <div class="col-xs-8 col-xs-offset-2"> <h1 class="text-center">登陆</h1> <div class="form-group"> <label for="username">用户名</label> <input type="text" name="username" id="username" class="form-control"> </div> <div class="form-group"> <label for="password">密码</label> <input type="text" name="password" id="password" class="form-control"> </div> <div class="form-group"> <label for="">验证码</label> <div class="row"> <div class="col-xs-6"> <input type="text" name="code" id="id_code" class="form-control"> </div> <div class="col-xs-6"> {% load static %} <img src="/get_code/" alt="" width="610px" height="35px" id="id_img"> </div> </div> </div> <input type="button" class="btn btn-success" value="登陆"> </div> </div> </div> <script> $("#id_img").click(function () { // 1 先获取标签之前的src let oldVal = $(this).attr('src'); $(this).attr('src',oldVal += '?') }) </script> </body>
登陆功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-xs-8 col-xs-offset-2"> <h1 class="text-center">登陆</h1> <div class="form-group"> <label for="username">用户名</label> <input type="text" name="username" id="username" class="form-control"> </div> <div class="form-group"> <label for="password">密码</label> <input type="text" name="password" id="password" class="form-control"> </div> <div class="form-group"> <label for="">验证码</label> <div class="row"> <div class="col-xs-6"> <input type="text" name="code" id="id_code" class="form-control"> </div> <div class="col-xs-6"> {% load static %} <img src="/get_code/" alt="" width="610px" height="35px" id="id_img"> </div> </div> </div> <input type="button" class="btn btn-success" value="登陆" id="id_commit"> <span style="color: red" id="error"></span> </div> </div> </div> <script> $("#id_img").click(function () { // 1 先获取标签之前的src let oldVal = $(this).attr('src'); $(this).attr('src',oldVal += '?') }) // 点击按钮发送ajax请求 $('#id_commit').click(function(){ $.ajax({ url:'', type:'post', data:{ 'username':$('#username').val(), 'password':$('#password').val(), 'code':$('#id_code').val(), // 结合需求合理选择 'csrfmiddlewaretoken':'{{ csrf_token }}' }, success:function (args){ if (args.code == 1000){ // 跳转到首页 window.location.href = args.url }else{ // 渲染错误信息 $('#error').text(args.msg) } } }) }) </script> </body> </html>
# 1.先校验验证码是否正确(忽略大小写:将其同一转成大写或小写比较) def login(request): if request.method == 'POST': back_dic = {'code':1000,'msg':''} username = request.POST.get('username') password = request.POST.get('password') code = request.POST.get('code') # 1 先校验验证码是否正确 自己决定是否忽略 统一转大写或者小写再比较 if request.session.get('code').upper() == code.upper(): # 2 校验用户名和密码是否正确 user_obj = auth.authenticate(request,username=username,password=password) if user_obj: # 保存用户状态 auth.login(request,user_obj) back_dic['url'] = '/home/' else: back_dic['code'] = 2000 back_dic['msg'] = '用户名或密码错误' else: back_dic['code'] = 3000 back_dic['msg'] = '验证码错误' return JsonResponse(back_dic) return render(request,'login.html')