1. 创建url (项目 / url.py)
from app01.views import login
urlpatterns = [
# 登陆页面
path("login/", account.login),
path("logout/", account.logout),
path("image/code/", account.image_code),
]
2. 创建图片验证码工具类(app01 / utils / code.py)
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
def check_code(width=120, height=30, char_length=5, font_file="Monaco.ttf", font_size=20):
code = []
# 创建一张图片
img = Image.new(mode="RGB", size=(width, height), color=(255, 255, 255))
# 创建一个画笔
draw = ImageDraw.Draw(img, mode="RGB")
def rndChar():
"""生成随机字母"""
# return chr(random.randint(65, 90))
"""随机数字"""
return str(random.randint(0, 9))
def rndColor():
"""随机生成颜色"""
return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 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)
3. 创建视图函数(app01 / views /login.py)
from django import forms
from django.http import HttpResponse
from django.shortcuts import render, redirect
# 使用form组件做登陆
from app01 import models
from app01.utils.bootstrap import BootStrapForm
from app01.utils.encrypt import md5
from app01.utils.code import check_code
class LoginForm(BootStrapForm):
# form需要自定义字段
username = forms.CharField(label="用户名",
widget=forms.TextInput,
required=True)
password = forms.CharField(label="密码",
widget=forms.PasswordInput(render_value=True), # render_value=True:在输入框保留用户输入的内容
required=True) # required=True: 必填
code = forms.CharField(label="验证码",
widget=forms.TextInput, # render_value=True:在输入框保留用户输入的内容
required=True) # required=True: 必填
# 定义一个钩子方法获取密码
def clean_password(self):
pwd = self.cleaned_data.get("password") # cleaned_data获取用户输入的内容: {'username': '123', 'password': '321'}
# {'username': '123', 'password': '933912614eaae2d0c86099673e398b0b'}
return md5(pwd) # 返回给前端结果
# # 使用modelfprm
# class LoginModelForm(forms.ModelForm):
# class Meta:
# # 直接去数据库里拿数据
# model = models.Admin
# fields = ["username", "password"]
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():
# 验证成功,获取到用户名和密码
# {'username': '123', 'password': '321',"code":"xxx"}
# print(form.cleaned_data) # form验证通过后只能form.cleaned_data验证
# 验证码效验,获取到剔除的验证码
user_input_code = form.cleaned_data.pop("code")
code = request.session.get("image_code", "")
print("=========", user_input_code, code)
if code.upper() != user_input_code.upper():
form.add_error("code", "验证码错误")
return render(request, "login.html", {"form": form})
# 去数据库效验用户名和密码是否正确,获取用户对象,如果错的就是None
# admin_object=models.Admin.objects.filter(username="form.cleaned_data["username]",password="form.cleaned_data["password]").first()
admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
if not admin_object:
# form / modelform可以 主动的 手动添加错误信息,(字段名,错误信息)
form.add_error("password", "用户名或密码错误")
# form.add_error("username", "用户名或密码错误")
return render(request, "login.html", {"form": form})
# 用户名和密码输入正确
# 网站生成随机字符串,写到用户浏览器的cookie中,在写入到session中
request.session["info"] = {"id": admin_object.id, "name": admin_object.username} # 会自动生成cookie和在服务器生成session
request.session.set_expiry(60 * 60 * 24 * 7) # 7天免登录
return redirect("/admin/list/")
return render(request, "login.html", {"form": form})
from io import BytesIO # 导入内存文件操作
def image_code(request):
"""生成验证图片"""
# 调用pillow函数,生成图片,img: 图片 ;code_string: 验证码内容
img, code_string = check_code()
# print("code_string=", code_string)
# 写入到自己的session中(以便于后续获取验证码在进行效验)
request.session["image_code"] = code_string
# 给验证码的 session设置60秒超时
request.session.set_expiry(60)
stream = BytesIO() # 创建实例对象
img.save(stream, "png") # 将图片保存到内存中
return HttpResponse(stream.getvalue()) # 再从内存中获取图片
def logout(request):
"""注销"""
# 清除当前session
request.session.clear()
return redirect("/login/")
4. 创建html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
<style>
.account{
width:400px;
border: 1px solid #dddddd;
border-radius: 5px;
box-shadow: 5px 5px 20px #aaa;
margin-left: auto;
margin-right: auto;
margin-top:100px;
padding: 20px 40px;
}
.account h2{
margin-top:10px;
text-align:center
}
</style>
</head>
<body>
<div class="account">
<h2>用户登录</h2>
<form method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label>用户名</label>
{{ form.username }}
<span style="color:red;">{{ form.username.errors.0 }}</span>
</div>
<div class="form-group">
<label>密码</label>
{{ form.password }}
<span style="color:red;">{{ form.password.errors.0 }}</span>
</div>
<div class="form-group">
<label>图片验证码</label>
<div class="row">
<div class="col-xs-7">
{{ form.code }}
<span style="color:red;">{{ form.code.errors.0 }}</span>
</div>
<div class="col-xs-5">
<img id="image_code" src="/image/code/" style="width:125px;">
</div>
</div>
</div>
<input type="submit" value="登 陆" class="btn btn-primary">
</form>
</div>
</body>
</html>
标签:code,return,form,randint,random,request,12,登陆,页面
From: https://www.cnblogs.com/kh-1314/p/17009994.html