图形验证码

安装验证码库

django-simple-captcha是Django的第三方库,用来生成一个图像验证码。

1
pip install django-simple-captcha

配置验证码

  • 添加应用

在INSTALLED_APPS配置中增加一列,内容为:captcha

1
2
3
4
5
6
7
8
9
10
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'App.apps.AppConfig',
'captcha',
]
  • 验证码设置:默认就是以下配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 注意、注意、注意
# TEMPLATES里的APP_DIRS要为True,否则找不到imagse.html
'APP_DIRS': True, #

# 图形验证码配置
CAPTCHA_IMAGESIZE = (8,45) # 设置captcha图片大小

CAPTCHA_LENGTH =4 #字符个数
CAPTCHA_TIMEOUT =1 #超时(minutes)*

# 输出格式:输入框验证码图片隐藏域
# '%(image)s %(hidden_field)s %(text_field)s'
CAPTCHA_OUTPUT_FORMAT ='%(text_field)s %(image)s %(hidden_field)s'

# 验证码干扰设置
CAPTCHA_NOISE_FUNCTIONS =(
'captcha.helpers.noise_null',
'captcha.helpers.noise_arcs',
'captcha.helpers.noise_dots',
)
# 验证码类型 captcha.helpers.random_char_challenge 随机字符串
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge'
  • 设置路由

在根路由中设置验证码路由:

1
path('captcha/',include("captcha.urls"))
  • 迁移数据库

因为验证码是用数据库存储,所以需要迁移一次数据库:

1
python manage.py migrate

使用验证码

  • 定义表单:forms.py
1
2
3
4
5
6
7
from django import forms
from captcha.fields import CaptchaField

class LoginFroms(forms.Form):
username = forms.CharField(required=True, min_length=3)
password = forms.CharField(required=True, min_length=6)
captcha = CaptchaField()
  • 定义视图:views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
from django.http import HttpResponse
from django.shortcuts import render
from App01.forms import LoginForms

def captcha(request):
if request.method == "POST":
form = LoginForms(request.POST)
if form.is_valid():
return HttpResponse("验证通过")
else:
return render(request, 'app01/login.html', locals())
form = LoginForms()
return render(request, 'app01/login.html', locals())
  • 定义模板:login.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码登录</title>
</head>
<body>
<form action="{% url 'App01:captcha' %}" method="post">
{% csrf_token %}
{{ form.username }}
<br>
{{ form.password }}
<br>
{{ form.captcha }}
{{ form.captcha.errors }}
<br>
<input type="submit">
</form>
</body>
</html>

邮件发送

配置发件人信息

1
2
3
4
5
6
7
8
9
10
11
12
## 邮件发送设置

EMAIL_HOST = 'smtp.qq.com'
# smtp服务固定的端口是25
EMAIL_PORT = 25

#发送邮件的邮箱
EMAIL_HOST_USER = '259380039@qq.com'
#在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = '*********' #smtp授权码
#收件人看到的发件人 <此处要和发送邮件的邮箱相同>
EMAIL_FROM = 'python<259380039@qq.com>'

调用send_mail

1
2
3
4
5
from django.core.mail import send_mail		# 导入Django邮件发送模块
from day07.settings import EMAIL_FROM # 导入发件人,也可以自定义一个
def send(request):
send_mail("测试邮件主题", "测试邮件内容", EMAIL_FROM, ['23223856@qq.com'])
return HttpResponse('邮件发送')

富文本编辑器

安装第三方库

1
2
3
pip install django-tinymce

# Successfully installed django-tinymce-3.1.0 安装成功提示

安装第三方应用

在settings的INSTALL_APPS列表里面添加tinymce应用:

1
2
3
4
5
6
7
8
9
10
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'App.apps.AppConfig',
'tinymce',
]

增加文本框配置

1
2
3
4
5
6
# 富⽂本编辑器的配置 默认配置
TINYMCE_DEFAULT_CONFIG = {
'theme':'advanced',
'width':600,
'height':400,
}

前台模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>富文本编辑器</title>
<script src="/static/tiny_mce/tiny_mce.js"></script>
<script>
tinyMCE.init({
'mode':'textareas',
'width':800,
'height':600,
})
</script>
</head>
<body>
<form action="/" method="POST">
{% csrf_token %}
<p>标题 <input type="text" name="title" placeholder="请输⼊标题" maxlength="20" required></p>
<textarea name="content" id="" cols="30" rows="10"></textarea>
<input type="submit">
</form>
</body>
</html>

文件上传

设置存储路径

在settings里设置上传路径,以下配置上传到静态文件目录下的uplaod目录:

1
2
3
UPLOAD_DIRS = [
os.path.join(STATICFILES_DIRS[0], 'upload'),
]

创建文件上传模板

和其他语言的文件上传没有区别,input类型为file即可,设置enctype=”multipart/form-data”,请求类型为post:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="test_file"> <br>
<input type="submit">
</form>
</body>
</html>

创建views处理函数

调用fobj = request.FILES.get(‘test_file’)返回一个文件上传对象,属性如下:

名称 说明
file.name 获取上传的名称
file.size 获取上传⽂件的大小(字节)
file.read() 读取全部(适⽤于⼩⽂件)
file.chunks() 按块来返回⽂件 通过for循环进⾏迭代,可以将⼤⽂ 件按照块来写⼊到服务器
file.multiple_chunks() 判断⽂件 是否⼤于2.5M 返回True或者False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def upload(request):
if request.method == 'POST':
fobj = request.FILES.get('test_file')
# 构造保存路径
savePath = os.path.join(settings.UPLOAD_DIRS[0], fobj.name)
print(savePath)
with open(savePath, 'wb') as f:
if fobj.multiple_chunks():
# 文件大于2.5MB,分页写入
for data in fobj.chunks:
f.write(data)
else:
# 文件小于2.5MB,直接写入
f.write(fobj.read())
return HttpResponse('文件上传成功')
return render(request, 'upload.html')

封装文件上传类

  • 函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import os
from datetime import datetime
from random import randint

"""
需求分析:
1、检查文件类型
2、检查文件大小
3、实现随机命名
"""

class FileUpload:

def __init__(self, fobj, exts=('jpg','png','gif'), size=1024*1024, is_randomname=False):
"""
:param fobj: 上传文件对象
:param exts: 允许上传的元组
:param size: 上传最大大小
:param is_randomname: 是否随机命名
"""
self.file = fobj
self.exts = exts
self.size = size
self.is_randomname = is_randomname

def upload(self, dest):
"""
:param path: 文件上传路径
:return: 成功返回路径,失败返回错误代码
"""
# 检查类型
if not self.check_type():
return -1 # 如果格式不服,返回-1

# 检查文件大小
if not self.check_size():
return -2 # 如果文件大于允许大小,返回-2

# 是否随机命名
if self.is_randomname:
self.file_name = self.randomname()
else:
self.file_name = self.file.name

# 拼接路径
path = os.path.join(dest, self.file_name)
self.save_file(path)
return path


def check_type(self):
ext = self.file.name
ext = ext.split('.')
ext = ext[len(ext)-1]
if ext in self.exts:
return True
return False

def check_size(self):
size = self.file.size
if size < self.size:
return True

return False

def randomname(self):
name = datetime.now().strftime("%Y%m%d%H%M%S_") + str(randint(1,10000))
ext = os.path.splitext(self.file.name)
ext = ext[1] if len(ext) > 1 else ''
name += ext
return name
def save_file(self,path):
with open(path, 'wb') as f:
if self.file.multiple_chunks():
for data in self.file.chunks():
f.write(data)
else:
f.write(self.file.read())
  • 调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
from App.upload import FileUpload
from day08 import settings

def upload(request):
if request.method == 'POST':
fobj = request.FILES.get('test_file')
# 构造保存路径
savePath = os.path.join(settings.UPLOAD_DIRS[0])
file = FileUpload(fobj, is_randomname=True)
res = file.upload(savePath)
print(res)
return HttpResponse("文件上传,返回值:" + str(res))

return render(request, 'upload.html')