登录功能
登录功能
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<script src="{% static 'bootstrap/js/jquery.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h2 class="text-center">登录</h2>
<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="password" name="password" id="password" class="form-control">
</div>
<div class="form-group">
<label for="code">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" id="code" name="code" class="form-control">
</div>
<div class="col-md-6">
<img src="/get_code/" alt="" height="35" width="310" id="img">//每次这里src的内容一改变,就会像这个url发送一次请求,用于电机改变验证码。
</div>
</div>
</div>
<button class="btn btn-primary" id="b1">登录</button>
<span id="error" style="color: red"></span>
</div>
</div>
</div>
<script>
$('#img').click(function () {
// 点击 修改src原来值
var oldVal = $(this).attr('src');
//只要每次url有变化,就会发送请求。所以这里用加减问号,但是不知道是浏览器内部还是django内部做了缓存,导致只能在两个验证码之间来回切换,而并没有发送请求,所以最好在后面加上一个时间戳。
if (oldVal.endsWith('?')){
$(this).attr('src','/get_code/')
}else{
$(this).attr('src',oldVal += '?')
}
});
$('#b1').click(function () {
$.ajax({
url:'',
type:'post',
data:{
'username':$('#username').val(),
'password':$('#password').val(),
'code':$('#code').val(),
'csrfmiddlewaretoken':'{{ csrf_token }}'
},
success:function (data) {
if (data.code == 1000){
window.location.href = data.url
}else{
// 渲染错误信息
$('#error').text(data.msg)
}
}
})
})
</script>
</body>
</html>
后端代码:
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(username=username,password=password)
if user_obj:
# 3 保存用户登录状态
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')
from PIL import Image,ImageDraw,ImageFont
import random
from io import BytesIO,StringIO
"""
BytesIO, 能够存储数据 并以二进制的格式再返回给你
StringIO 能够存储数据 并以字符串的格式再返回给你
"""
"""
Image, 产生图片的
ImageDraw, 产生画笔的
ImageFont 控制字体样式
"""
def get_random():
return random.randint(0,255),random.randint(0,255),random.randint(0,255)
# 图片验证码相关
def get_code(request):
# 推到思路1:直接拿后端现成的图片 二进制模式打开发送
# with open(r'D:\上海Python11期视频\python11期视频\BBS\avatar\u205777803476556477fm26gp0.jpg','rb') as f:
# data = f.read()
# return HttpResponse(data)
# 推导思路2:利用模块产生图片 再发送给前端 pillow
# img_obj = Image.new('RGB',(310,35),'green') # 生成了一个图片对象
# img_obj = Image.new('RGB',(310,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()
# return HttpResponse(data)
# 推到思路3:不再利用文件存取数据 借助于内存管理器
# img_obj = Image.new('RGB',(310,35),get_random())
# io_obj = BytesIO() # 生成一个内存管理器对象
# img_obj.save(io_obj,'png') # 你可以将io_obj当成文件句柄f
# return HttpResponse(io_obj.getvalue()) # 以二进制的方式取出数据
# 推到思路4(终极步骤) 图片上写字
img_obj = Image.new('RGB',(310,35),get_random())
img_draw = ImageDraw.Draw(img_obj) # 生成一个画笔对象
img_font = ImageFont.truetype('static/font/111.ttf',30) # 字体的样式
"""
所有的字体样式都是由.ttf结尾的文件控制的
"""
# 随机生成验证码 a~z A~Z 0~9
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))
temp = random.choice([random_upper,random_lower,random_int])
# 将产生的随机字符写到图片上
img_draw.text((i*45+45,0),temp,get_random(),img_font)
code += temp
print(code)
# 将随机验证码存储取来 以便其他函数调用
request.session['code'] = code
io_obj = BytesIO()
img_obj.save(io_obj,'png')
return HttpResponse(io_obj.getvalue())
get_code方法就是用来获取随机验证码的,里面还加了背景颜色变变变。