# 1 创建数据库project
mysql -uroot -p123456
create database project default charset utf8;
# 2 创建项目project
django-admin startproject project
# 3 安装所需三方库
pip install django==3.2.13
pip install pillow==8.4.0
pip install pymysql
# 4 创建应用app01
cd project
python manage.py startapp app01
# 添加app01应用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config', # 新增
]
# 添加数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'project',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '192.168.144.3',
'PORT': '3306',
}
}
# 静态文件配置
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
from django.contrib import admin
from django.urls import path, include, re_path
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', include('app01.urls')),
]
from django.urls import path, include, re_path
from . import views
urlpatterns = [
path('', views.MyClassView.as_view()),
path('image/code/', views.ImageCode.as_view()),
]
from django.db import models
class LoginDatabase(models.Model):
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=32)
class Meta:
db_table = 'login'
def __str__(self):
return self.username
from django import forms
from . import models
from django.forms import widgets
class LoginModelForm(forms.ModelForm):
verify_code = forms.CharField(
label='验证码',
widget=forms.TextInput(attrs={'class': "form-control"})
)
class Meta:
model = models.LoginDatabase
fields = "__all__"
labels = {"username": "名字", "password": "密码", "verify_code ": "验证码"}
widgets = {
# 不同类型的字段要用不同的属性输出,不然表单的格式验证失效
# 给不同字段添加class属性,改变样式
"username": widgets.TextInput({"class": "form-control"}),
"password": widgets.PasswordInput({"class": "form-control"}),
}
error_messages = {"password": {"invalid": "请填写正确的密码格式"}}
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
# print(self.fields)
# for name, filed in self.fields.items():
# filed.widget.attrs = {"class": "form-control", "placeholder": filed.label}
from PIL import Image,ImageDraw,ImageFilter,ImageFont
import random
def check_code(width=140, height=40, char_length=4, font_file='kumo.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(2, 6)
draw.text([i * width / char_length, h], char, font=font, fill=rndColor())
# draw.text([i * width / char_length, h], char, fill=rndColor(), font_size=150)
# 写干扰点
# 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__':
pass
img, code_str = check_code()
print(img,code_str)
with open('code.png', 'wb') as f:
img.save(f, format='png')
# 1. 直接打开
# img,code = check_code()
# img.show()
# 2. 写入文件
# img,code = check_code()
# with open('code.png','wb') as f:
# img.save(f,format='png')
# 3. 写入内存(Python3)
# from io import BytesIO
# stream = BytesIO()
# img.save(stream, 'png')
# stream.getvalue()
# 4. 写入内存(Python2)
# import StringIO
# stream = StringIO.StringIO()
# img.save(stream, 'png')
# stream.getvalue()
字体文件链接:点击这里
使用 kumo.ttf 字体文件存放目录和app01同级
from django.shortcuts import render, HttpResponse, redirect
from django.views.generic import View
from . import forms, models
from io import BytesIO
from utils.code import check_code
class MyClassView(View):
"""类视图"""
def get(self, request):
"""处理GET请求"""
form = forms.LoginModelForm()
# print(request.session.get('image_code'))
return render(request, 'register.html', {'form': form})
def post(self, request):
"""处理POST请求"""
form = forms.LoginModelForm(data=request.POST)
if form.is_valid():
verify_code = form.cleaned_data.pop('verify_code')
data = models.LoginDatabase.objects.filter(**form.cleaned_data).first()
if data and (verify_code == request.session.get('image_code')):
return redirect('https://www.baidu.com')
else:
form.add_error('password', '用户名或密码错误')
return render(request, 'register.html', {'form': form})
return render(request, 'register.html', {'form': form})
class ImageCode(View):
def get(self, request):
img, code_str = check_code()
stream = BytesIO()
img.save(stream, 'png')
request.session['image_code'] = code_str
request.session.set_expiry(60)
# stream.getvalue() 写入内存
return HttpResponse(stream.getvalue())
{% load static %}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link href="https://fastly.jsdelivr.net/npm/@bootcss/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.navbar{
border-radius: 0;
}
.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>{{ form.username.errors.0 }}span>
div>
<div class="form-group">
<label>密码label>
{{ form.password }}
<span>{{ form.password.errors.0 }}span>
div>
<div class="form-group">
<label >图片验证码label>
<div class="row">
<div class="col-xs-7">
{{ form.verify_code }}
<span>{{ form.verify_code.errors.0 }}span>
<span style="color: red;">span>
div>
<div class="col-xs-5">
<img id="image_code" src="/login/image/code/" alt="" style="width: 125px;">
div>
div>
div>
<input type="submit" value="登录" class="btn btn-primary">
form>
div>
<script src="https://fastly.jsdelivr.net/npm/@bootcss/[email protected]/dist/js/bootstrap.min.js">script>
<script src="https://fastly.jsdelivr.net/npm/[email protected]/dist/jquery.min.js">script>
<script src="https://fastly.jsdelivr.net/npm/[email protected]/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous">script>
<script>window.jQuery || document.write('