【Django】教程-1-安装+创建项目+目录结构介绍
【Django】教程-2-前端-目录结构介绍
【Django】教程-3-数据库相关介绍
【Django】教程-4-一个增删改查的Demo
【Django】教程-5-ModelForm增删改查+规则校验【正则+钩子函数】
【Django】教程-6-搜索框-条件查询前后端
【Django】教程-7-分页,默认使用django的
【Django】教程-8-页面时间组件
【Django】教程-9-登录+退出
【Django】教程-10-ajax请求Demo,结合使用
【Django】教程-11-ajax弹窗实现增删改查
【Django】教程-12-柱状图
【Django】教程-13-饼图,折线图
19 .验证码+登录页
验证码工具类 captcha_utils.py
from PIL import Image, ImageDraw, ImageFont
import random
import string
def generate_captcha(length=4, size=(120, 30), font_size=20):
""" 一个可以返回验证码的,方法
Returns:
list:
- image,验证码图
- captcha_text,验证码字符串
"""
# 定义验证码字符集
characters = string.ascii_letters + string.digits
# 随机生成验证码
captcha_text = ''.join(random.choice(characters) for _ in range(length))
# 创建一个彩色图像,背景颜色选择较浅的色调
background_color = (
random.randint(200, 255),
random.randint(200, 255),
random.randint(200, 255)
)
image = Image.new('RGB', size, color=background_color)
draw = ImageDraw.Draw(image)
# 选择字体
font = ImageFont.load_default()
# 也可以使用自定义字体,例如:
# font = ImageFont.truetype('arial.ttf', font_size)
# 绘制验证码字符,字体颜色选择较深的色调
for i, char in enumerate(captcha_text):
char_color = (
random.randint(0, 100),
random.randint(0, 100),
random.randint(0, 100)
)
draw.text((10 + i * 25, 10), char, fill=char_color, font=font)
# 添加干扰线
for _ in range(5):
line_color = (
random.randint(150, 255),
random.randint(150, 255),
random.randint(150, 255)
)
x1 = random.randint(0, size[0])
y1 = random.randint(0, size[1])
x2 = random.randint(0, size[0])
y2 = random.randint(0, size[1])
draw.line((x1, y1, x2, y2), fill=line_color, width=2)
# 添加干扰点
for _ in range(20):
point_color = (
random.randint(150, 255),
random.randint(150, 255),
random.randint(150, 255)
)
x = random.randint(0, size[0])
y = random.randint(0, size[1])
draw.point((x, y), fill=point_color)
return image, captcha_text
登录页 login.html
{% load static %}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录页面</title>
<!-- 引入 Bootstrap 的 CSS 文件 -->
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.css' %}"/>
<style>
/* 自定义一些样式让页面更美观 */
body {
background-color: #f8f9fa;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}
.login-card {
background-color: white;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
padding: 2rem;
width: 350px;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-control {
height: calc(2.25rem + 2px);
}
.btn-login {
width: 100%;
padding: 0.75rem;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.btn-login:hover {
background-color: #0056b3;
}
.register-link {
text-align: center;
margin-top: 1rem;
}
.register-link a {
color: #007bff;
text-decoration: none;
}
.register-link a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container login-card">
<h2 class="text-center mb-4">用户登录</h2>
<form method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label>用户名:</label>
{{ user.username }}
<span style="color: red">{{ user.username.errors.0 }}</span>
</div>
<div class="form-group">
<label>密码:</label>
{{ user.password }}
<span style="color: red">{{ user.password.errors.0 }}</span>
</div>
<div class="form-group">
<label>验证码:</label>
<img id="captcha-image" class="img-fluid" src="/captcha/get" >
{{ user.captcha }}
<span style="color: red">{{ user.captcha.errors.0 }}</span>
</div>
<button type="submit" class="btn-login">登录</button>
</form>
<div class="register-link">
还没有账号?<a href="#">立即注册</a>
</div>
</div>
<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.js' %}"></script>
<script>
$(document).ready(function () {
$('#captcha-image').click(function () {
$.ajax({
url: '/captcha/get',
type: 'GET',
success: function (response) {
$('#captcha-image').attr('src', '/captcha/get');
// 可以在这里清空验证码输入框
{#$('input[name="captcha"]').val('');#}
},
error: function () {
alert('刷新验证码失败');
}
});
});
});
</script>
</body>
</html>
业务控制层login_view.py
import io
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_exempt
from appTang.forms import LoginForm
from appTang.models import Admin
from appTang.util.captcha_utils import generate_captcha
def login(req):
"""用户登录"""
""" modelform 方式添加用户"""
if req.method == 'GET':
user = LoginForm()
return render(req, 'login/login.html', {"user": user})
# 用户post提交,数据校验
user = LoginForm(data=req.POST)
if user.is_valid():
# username = req.POST.get("username")
username = user.clean_username()
user = Admin.objects.filter(username=username).first()
# 需要添加用户认证成功信息
req.session["info"] = {"username": username, 'id': user.id}
captcha = req.POST.get("captcha")
image_code = req.session.get('captcha', '') # 超时时,没有,给个''
# 不区分大小写比较
if image_code.upper() == captcha.upper():
# 登录成功设置session,超时时间
req.session.set_expiry(60 * 60 * 24 * 7) # 7天免登录
return redirect("/admin/list")
else:
user = LoginForm(data=req.POST)
user.add_error('captcha', '验证码输入错误')
# # 校验失败, 在页面上展示错误信息
return render(req, 'login/login.html', {"user": user})
def logout(req):
"""注销"""
req.session.clear();
return redirect("/login/")
def get_captcha(request):
""" 获取 验证码 """
image, captcha_text = generate_captcha()
# 将验证码存储在会话中
request.session['captcha'] = captcha_text
# 设置超时时间
request.session.set_expiry(60)
# 将图片保存到内存中
buffer = io.BytesIO()
image.save(buffer, 'PNG')
# buffer.seek(0)
print(captcha_text)
# 返回图片响应
return HttpResponse(buffer.getvalue())
forms.py
from django import forms
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from . import models
from .models import Department, UserInfo, Admin, Order
from .util.md5 import md5
class BootstrapModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 循环Modelform中所有字段,给每个字段插件设置
for name, field in self.fields.items():
if field.widget.attrs:
field.widget.attrs["class"] = "form-control"
field.widget.attrs["placeholder"] = field.label
else:
field.widget.attrs = {"class": "form-control", "placeholder": field.label}
# 登录Form
class LoginForm(BootstrapModelForm):
captcha = forms.CharField(label="验证码", widget=forms.TextInput())
class Meta:
model = Admin
# 字段按照顺序加载
fields = ['username', 'password', 'captcha']
widgets = {
"password": forms.PasswordInput(render_value=True)
}
def clean_username(self):
username = self.cleaned_data.get("username")
if not Admin.objects.filter(username=username).exists():
# raise ValidationError("用户名不存在!")
raise ValidationError("用户名或密码错误!")
return username
def clean_password(self):
password = self.cleaned_data.get("password")
username = self.cleaned_data.get("username")
if not Admin.objects.filter(username=username, password=md5(password)).exists():
# raise ValidationError("密码不正确!")
raise ValidationError("用户名或密码错误!")
return md5(password)
models.py
from django.utils import timezone
from django.db import models
class Admin(models.Model):
"""管理员"""
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=64)