涉及知识点:
- 生成登陆验证码
- 实现单用户登陆
- 压缩图片
1.压缩图片大小
from PIL import Image
img = Image.open('1.jpg')
# 获得原图片的像素值
size = img.size
# 用抗锯齿模式生成缩略图
img.thumbnail(size, Image.ANTIALIAS)
# 生成的图片像素不变,磁盘大小变小
img.save('new.jpg')
2.Django中生成验证码
1.前端页面请求验证码图片
<form action="/login_/" method="post">
{% csrf_token %}
<p>用户名:<input type="text" name="username" required></p>
<p>密码:<input type="password" name="password" required></p>
<input type="hidden" value="{{ count }}" name="count">
// 两次登陆失败,则需输入验证码
{% if count > 2 %}
<p>请输入验证码:<input type="text" name="verify" required>
<img src="/test/verifycode/" id="verifyImg"></p>
{% endif %}
<button>提交</button>
</form>
<script>
$(function () {
// 点击验证码时在url后追加随机数字,图片链接改变后浏览器会自动刷新图片
$('#verifyImg').click(function () {
$(this).prop('src','/test/verifycode/'+Math.random());
});
})
</script>
2.验证码图片对应的视图处理函数
from PIL import Image, ImageDraw, ImageFont
import random, string, io
from django.shortcuts import HttpResponse, render
# 返回随机色
def rndColor():
c1 = random.randrange(0, 220)
c2 = random.randrange(0, 220)
c3 = random.randrange(0, 220)
return (c1, c2, c3)
def verifycode(request):
'''用于生成随机验证码,返回验证码图片并将随机字符保存进session'''
base_str = string.ascii_letters + string.digits
# 返回4位随机验证码列表
rnd_list = random.sample(base_str, 4)
rnd_str = ''.join(rnd_list)
# 保存验证码到session
request.session['verifycode'] = rnd_str.lower()
# 创建图片对象
bgcolor = 'lightgray'
width, height = 100, 25
img = Image.new('RGB', (width, height), bgcolor)
# 关联字体文件,设置字体大小
font = ImageFont.truetype('/usr/share/fonts/truetype/fonts-japanese-gothic.ttf', 22)
# 创建图片的画笔对象并书写验证码
draw = ImageDraw.Draw(img)
font_color = rndColor()
draw.text((20, 2), rnd_str, fill=font_color, font=font)
# 随机生成100个散点
for i in range(100):
xy = (random.randint(0, width), random.randint(0, height))
draw.point(xy, fill=rndColor())
# 生成随机直线
for i in range(5):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(0, width)
y2 = random.randint(0, height)
draw.line(xy=(x1, y1, x2, y2), fill=rndColor(), width=1)
# 生成随机圆
for i in range(5):
x = random.randint(0, width)
y = random.randint(0, height)
draw.arc((x, y, x + 5, y + 5), 0, 360, fill=rndColor())
# 开辟二进制内存空间,存储图片
buf = io.BytesIO()
img.save(buf, 'png')
return HttpResponse(buf.getvalue())
3.登陆逻辑
from django.contrib.sessions.models import Session
from django.contrib import auth
from django.utils import timezone
def login_(request):
if request.method == 'POST':
if int(request.POST.get('count',0)) > 2:
verify = request.POST.get('verify').lower()
if verify != request.session['verifycode']:
return render(request,'login.html',{'message':'验证码错误'})
username = request.POST.get('username')
password = request.POST.get('password')
user = auth.authenticate(username=username,password=password)
if user is not None and user.is_active:
auth.login(request,user)
#挤掉之前登录的同一个账号
# 删除非当前用户session_key的记录
#查出的session,打印出来为session_key,可能是对象,本次登录的用户id并不会存进session中
for session in Session.objects.filter(expire_date__gte=timezone.now()):
data = session.get_decoded()
if data.get('_auth_user_id', None) == str(request.user.id):
session.delete()
return redirect(request.COOKIES['origin_url'])
else:
count = int(request.POST.get('count',1)) + 1
return render(request,'login.html',{'message':'用户名或密码错误','count':count})
return render(request,'login.html',{'message':'哪来的?','count':1})