【Django基础】Django编写图形验证码
下载字体
到https://files-cdn.cnblogs.com/files/wupeiqi/%E9%AA%8C%E8%AF%81%E7%A0%81%E5%AD%97%E4%BD%93%E6%96%87%E4%BB%B6.zip
生成图形验证码函数
from PIL import Image, ImageDraw, ImageFilter, ImageFont
import random
def check_code(width=120, height=30, char_length=5, font_file='employee_management/utils/ttf/Monaco.ttf', font_size=28):
code = []
img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
draw = ImageDraw.Draw(img, mode='RGB')
def rndChar():
"""
生成随机字母
:return:
"""
return chr(random.randint(65, 90))
def rndColor():
"""
生成随机颜色
:return:
"""
return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))
# 写文字
font = ImageFont.truetype(font_file, font_size)
for i in range(char_length):
char = rndChar()
code.append(char)
h = random.randint(0, 4)
draw.text([i * width / char_length, h], char, font=font, fill=rndColor())
# 写干扰点
for i in range(40):
draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
# 写干扰圆圈
for i in range(40):
draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
x = random.randint(0, width)
y = random.randint(0, height)
draw.arc((x, y, x + 4, y + 4), 0, 90, 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((x1, y1, x2, y2), fill=rndColor())
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
return img,''.join(code)
if __name__ == '__main__':
img, code_str = check_code()
print(code_str)
with open('code.png', 'wb') as f:
img.save(f, format='png')
获取验证码
# views.py函数
def image_code(request):
""" 生成图片验证码 """
# 调用pillow函数,生成图片
img, code_string = check_code()
# 写入到自己的session中,以便于后续获取验证码再进行校验
request.session['image_code'] = code_string
# 给session设置 60s 超时
request.session.set_expiry(60)
stream = BytesIO()
img.save(stream, 'png')
return HttpResponse(stream.getvalue())
验证码校验
def login(request):
"""登录"""
if request.method == "GET":
form = LoginForm()
return render(request, 'login.html', {"form": form})
form = LoginForm(data=request.POST)
if form.is_valid():
# 验证成功, 获取到的用户名和密码
print(form.cleaned_data)
# {'username': '123', 'password': '123'}
# {'username': '456', 'password': '0f54af32f41a5ba8ef3a2d40cd6ccf25'}
# 验证码的校验
user_input_code = form.cleaned_data.pop('code')
image_code = request.session.get('image_code', "")
print("user_input_code={}, image_code={}".format(user_input_code, image_code))
if image_code.upper() != user_input_code.upper():
form.add_error("code", "验证码错误")
return render(request, 'login.html', {"form": form})
# 去数据库校验用户名和密码是否正确
admin_object = Admin.objects.filter(**form.cleaned_data).first()
if not admin_object:
form.add_error("password", "用户名或密码错误")
return render(request, 'login.html', {"form": form})
# 如果用户名密码和验证码正确
# 网站生成随机字符创,写到用户浏览器的cookie中,再写入到服务器的session中
request.session["info"] = {'id': admin_object.id, 'name': admin_object.username}
# 重新设置session的超时时间,因为之前设置的session的超时时间的 60s
request.session.set_expiry(60 * 60 * 24)
return redirect("/admin/list/")
return render(request, 'login.html', {"form": form})
刷新验证码
第一种
<img src="/image/code/" alt="" id="image_code" onclick="this.setAttribute('src','/image/code/?random='+Math.random())">
第二种
将图片验证码设置ID,并将ID绑定一个事件
// 设置ID
...
...
{% if field.name == 'code' %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
<div class="row">
<div class="col-xs-7">
{{ field }}
<span class="error-msg">{{ field.errors.0 }}</span>
</div>
<div class="col-xs-5">
<img src="{% url 'image_code' %}" id="imageCode" title="点击更换图片">
</div>
</div>
</div>
{% else %}
...
...
// 绑定事件
...
...
{% block js %}
<script>
$(function () {
$('#imageCode').click(function () {
var oldSrc = $(this).attr('src');
$(this).attr('src', oldSrc + "?");
})
})
</script>
{% endblock %}

浙公网安备 33010602011771号