登录功能
思路分析
登录页面,我们还是采用ajax的方式提交用户数据
唯一需要学习的是如何制作图片验证码!
具体的登录页面效果图如下:
如何制作图片验证码
推导步骤1:在img标签的src属性里放上验证码的请求路径
补充1.img的src属性:
1.图片路径
2.url
3.图片的二进制数据
补充2:字体样式
我们计算机上之所以可以输出各种各样的字体样式,其内部其实对应的是一个个以.ttf结尾的文件
由于img的src属性里可以放图片的二进制数据,因此我们可以在src里放上图片的请求路径,返回的是一个图片的二进制数据
<img src="/get_code/" alt="" width="350" height="35">
# 该视图函数返回的是图片的二进制数据,图片是本地已有的图片路径
def get_code(request):
with open ("static/img/default.png","rb") as f:
data = f.read()
return HttpResponse(data)
字体样式网站
推导步骤2:利用pillow模块动态产生图片
"""
图片相关的模块:
pip3 install pillow
导入:from PIL import Image,ImageDraw,ImageFont
Image:生成图片
ImageDraw:能够在图片上乱涂乱画
ImageFont:控制字体样式
"""
from PIL import Image,ImageDraw,ImageFont
import random
def get_random():
return random.randint(0,255),random.randint(0,255),random.randint(0,255),
def get_code(request):
1.先产生一个图片,new方法的第一个参数是固定模式RGB格式,第二个是图片大小(宽,高),第三个是图片颜色(可以放rgb模式的颜色)
# image_obj = Image.new("RGB",(350,35),"green") # 固定颜色
# image_obj = Image.new("RGB",(350,35),(23,43,53)) # 变形1
image_obj = Image.new("RGB", (350, 35), get_random()) # 变形2
2.将产生的图片存起来,打开一个文件,该图片有一个save方法可以存储图片,第一个参数是文件句柄,第二个是存储图片格式
with open("xxx.png","wb") as f:
image_obj.save(f,"png")
3.再将图片以二进制形式读出来,返回给img标签的src属性
with open("xxx.png","rb") as f:
data = f.read()
return HttpResponse(data)
上述方法:会进行频繁的文件存储IO操作,效率比较低下,步骤4利用内存管理器模块优化!
推导步骤4:利用内存管理器模块优化
"""
导入内存管理器模块:from io import BytesIO,StringIO
BytesIO:功能临时帮您存储数据,返回的数据是二进制
StringIO:功能临时帮您存储数据,返回的数据是字符串
"""
def get_code(request):
# 1.同样先生成一个图片对象
image_obj = Image.new("RGB", (350, 35), get_random())
# 2.这里再生成一个内存管理器对象,就可以看成是f文件句柄
io_obj = BytesIO()
# 3.将图片保存到文件管理器对象里
image_obj.save(io_obj,"png")
# 4.把图片从文件管理器对象里取出来,用getvalue()方法
return HttpResponse(io_obj.getvalue())
最终步骤:写图片验证码
def get_code(request):
# 1.同样先生成一个图片对象
image_obj = Image.new("RGB", (350, 35), get_random())
# 2.在图片上生成一个画笔对象
img_draw = ImageDraw.Draw(image_obj)
# 3.设置字体样式,truetype()第一个参数是字体样式路径,第二个是字体大小
img_font = ImageFont.truetype("static/font/222.ttf",30)
# 4.随机生成验证码,五位,大小写字母、数字
code = ""
for i in range(5):
random_upper = chr(random.randint(65,90)) # 65-90的数字使用chr()函数对应转成大写字母
random_lower = chr(random.randint(97,122)) # 97-122的数字使用chr()函数对应转成小写字母
random_int = str(random.randint(0,9))
# 从上面三种随机选择一种
tmp = random.choice([random_int,random_lower,random_upper])
# 将产生的随机字符串写到图片上
"""
text()方法的第一个参数,字符串在图片上的坐标,第二个是字符串,
第三个字符串的颜色,第四个字体样式和大小
"""
img_draw.text((i*60,0),tmp,get_random(),img_font)
code += tmp
print(code)
# 5.将生成的随机验证码保存起来,因为在登录的视图函数需要用到,进行比对
request.session["code"] = code
# 6.再生成一个内存管理器对象,就可以看成是f文件句柄
io_obj = BytesIO()
# 7.将图片保存到文件管理器对象里
image_obj.save(io_obj,"png")
# 8.把图片从文件管理器对象里取出来,用getvalue()方法
return HttpResponse(io_obj.getvalue())
补充
如何让用户一点验证码图片就刷新验证码
<img src="/get_code/" alt="" width="350" height="35" id="img">
<script>
$("#img").click(function (){
let OldUrl = $(this).attr("src")
$(this).attr("src",OldUrl += "?")
})
</script>
向后端提交用户登录数据
前端:
// 点击登录按钮向后端发送ajax请求
$("#commit").click(function (){
$.ajax({
type:"post",
url:"",
data:{
"username": $("#id_username").val(),
"password": $("#id_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)
}
}
})
})
后端:
# 二、登录页面
def login(request):
# 1.判断是否为ajax请求
if request.method == "POST":
back_dic = {"code":1000,"msg":""}
# 2.获取用户提交的登录数据
username = request.POST.get("username")
password = request.POST.get("password")
code = request.POST.get("code")
# 3.判断验证码是否正确
if code.upper() == request.session["code"].upper():
# 4.利用auth模块判断用户名和密码是否正确
user_obj = auth.authenticate(request,username=username,password=password)
if user_obj:
# 5.正确则保存用户状态
auth.login(request,user_obj)
# 6.跳转到主页
back_dic["url"] = "/home/"
else:
# 7.错误信息展示
back_dic["code"] = 1001
back_dic["msg"] = "用户名或者密码不正确"
else:
back_dic["code"] = 1002
back_dic["msg"] = "验证码不正确"
return JsonResponse(back_dic)
return render(request,"login.html",locals())