⼀、图形验证码
1 安装django-simple-captcha库
在网站开发的登录页面中,经常会需要使用到图形验证码来验证。在 Django中,django-simple-captcha库包提供了图形验证码的使用。
$ pip install django-simple-captcha
# 如果安装有依赖库问题,请执⾏下⾯的安装
apt-get -y install libz-dev libjpeg-dev libfreetype6-dev python-dev
2 设置
图1 安装应用
图2. 设置验证码样式
图3. 设置路由
最后要迁移数据库:
python manage.py migrate
3 建立表单
# forms.py
from django import forms
from captcha.fields import CaptchaField
class LoginForm(forms.Form):
username = forms.CharField(max_length=20,min_length=3)
password =
forms.CharField(max_length=128,widget=forms.PasswordInput())
captcha = CaptchaField() # 验证码字段
4 实现
# 应⽤的urls.py
urlpatterns = [
.....
path('yzm/',views.user_login,name='yzm'),
]
# 前端⻚⾯
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<div>{{ msg }}</div>
<form action="{% url 'App03:yzm' %}" method="post">
{% csrf_token %}
⽤户:{{ form.username }} <span>{{ form.username.errors.0 }}
</span> <br>
密码:{{ form.password }} <span>{{ form.password.errors.0 }}
</span><br>
验证码:{{ form.captcha }} <span>{{ form.captcha.errors.0 }}
</span><br>
<input type="submit">
</form>
</body>
</html>
<script src="https://cdn.bootcss.com/jquery/1.12.3/jquery.min.js">
</script>
<script>
//点击刷新验证码
$(function () {
$('.captcha').css({
'cursor': 'pointer'
});
// ajax刷新
$('.captcha').click(function () {
console.log('click');
$.get("/app3/refresh/",
function (result) {
$('.captcha').attr('src', result['image_url']);
$('#id_captcha_0').val(result['key'])
});
});
})
</script>
# views.py
import json
from captcha.helpers import captcha_image_url
from captcha.models import CaptchaStore
from django.contrib.auth import authenticate
import django.contrib.auth as auth
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
def user_login(request):
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user =
authenticate(request,username=username,password=password)
if user:
auth.login(request,user)
return redirect(reverse("App03:home"))
else:
form = LoginForm()
# 跳转登录⻚⾯
return render(request,'App03/login.html',context={'form':form})
⼆、发送邮件
1.setting配置
# smtp服务的邮箱服务器
EMAIL_HOST = 'smtp.163.com'
# smtp服务固定的端⼝是25
EMAIL_PORT = 25
#发送邮件的邮箱
EMAIL_HOST_USER = 'landmark_cheng@163.com'
#在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = 'q123456'
#收件⼈看到的发件⼈ <此处要和发送邮件的邮箱相同>
EMAIL_FROM = 'python<landmark_cheng@163.com>'
2.发送邮件
#⼀封邮件
from django.core.mail import send_mail
from django.conf import settings
def sendone(request):
send_mail('标题', '内容', settings.EMAIL_FROM,
['313728420@qq.com'])
return HttpResponse("发⼀封邮件")
# 发多封邮件
def sendmany(request):
message1 = ('Subject here', '<b>Here is the message</b>',
settings.EMAIL_FROM, ['313728420@qq.com'])
message2 = ('Subject here', '<b>Here is the message</b>',
settings.EMAIL_FROM, ['313728420@qq.com'])
send_mass_mail((message1,message2), fail_silently=False)
return HttpResponse('发送多封邮件')
#渲染模板进⾏邮件发送
def send_mail(request):
subject, from_email, to = 'html', settings.EMAIL_FROM,
'313728420@qq.com'
html_content =
loader.get_template('active.html').render({'username': '⼩花猫'})
msg = EmailMultiAlternatives(subject, from_email=from_email, to=
[to])
msg.attach_alternative(html_content, "text/html")
msg.send()
return HttpResponse('发送html的⽂件内容')
三、富文本编辑器
一般用于写文章编辑內容自带样式
- 安装:pip install django-tinymce
- 配置
(1) 配置settings文件
在INSTALL_APPS 添加如下代码
INSTALLED_APPS = [
...
'App',
'tinymce',
]
在settings.py下添加如下代码
#富⽂本编辑器的配置
TINYMCE_DEFAULT_CONFIG = {
'theme':'advanced',
'width':600,
'height':400
}
(2) 添加视图函数
def index(req):
if req.method == 'GET':
return render(req,'index.html')
if req.method == 'POST':
# print(req.POST)
Posts(title=req.POST.get('title'),content=req.POST.get('content')).sa
ve()
return HttpResponse('index')
(3) 前台模板的展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>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>
四、文件上传
使用request.FILES 获取上传文件
1.表单注意
- 表单的enctype的值需要设置为:enctype="multipart/form-data
- 表单提交类型为POST
2.存储路径
在settings.py文件下添加如下代码
#设置上传⽂件路径
MEDIA_ROOT = os.path.join(BASE_DIR,'static/upload')
3. 文件上传对象的属性和方法
名称 | 说明 |
---|---|
file.name | 获取上传的名称 |
file.size | 获取上传大件的大小(字节) |
file.read() | 读取全部(适用于小⽂件) |
file.chunks() | 按块来返回文件 通过for循环进行迭代,可以将大⽂ 件按照块来写入到服务器 |
file.multiple_chunks() | 判断文件 是否大于2.5M 返回True或者False |
4.创建上传文件的表单
- 模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/doUpload/" method="post" enctype="multipart/formdata">
{% csrf_token %}
<p>⽂件 <input type="file" name="file"></p>
<p><input type="submit" value=
"上传"></p>
</form>
</body>
</html>
- views.py
from django.conf import settings
import os
#⽂件上传处理
def doUpload(req):
file = req.FILES.get('file')
# print(file.name)
# print(file.size)
savePath = os.path.join(settings.MDEIA_ROOT,file.name)
# print(savePath)
with open(savePath,'wb') as f:
# f.write(file.read())
if file.multiple_chunks():
for myf in file.chunks():
f.write(myf)
print('⼤于2.5')
else:
print('⼩于2.5')
f.write(file.read())
return HttpResponse('⽂件上传')
5.封装文件上传类
可以自定义⼀个类实现文件上传,文件上传类可以:
- 检查文件类型
- 检查文件大小
- 是否生成随机文件名
import os
from datetime import datetime
from random import randint
class FileUpload:
def __init__(self,file,exts=['png','jpg','jpeg'],size=1024*1024,is_randomname=False):
"""
:param file: ⽂件上传对象
:param exts: ⽂件类型
:param size: ⽂件⼤⼩,默认1M
:param is_randomname: 是否是随机⽂件名,默认是否
"""
self.file = file
self.exts = exts
self.size = size
self.is_randomname = is_randomname
#⽂件上传
def upload(self,dest):
"""
:param dest: ⽂件上传的⽬标⽬录
:return:
"""
#1 判断⽂件类型是否匹配
if not self.check_type():
return -1
#2 判断⽂件⼤⼩是否符合要求
if not self.check_size():
return -2
#3 如果是随机⽂件名,要⽣成随机⽂件名
if self.is_randomname:
self.file_name = self.random_filename()
else:
self.file_name = self.file.name
#4 拼接⽬标⽂件路径
path = os.path.join(dest,self.file_name)
#5 保存⽂件
self.write_file(path)
return 1
def check_type(self):
ext = os.path.splitext(self.file.name)
if len(ext) > 1:
ext = ext[1].lstrip('.')
if ext in self.exts:
return True
return False
def check_size(self):
if self.size < 0:
return False
#如果⽂件⼤⼩于给定⼤⼩,返回True,否则返回False
return self.file.size <= self.size
def random_filename(self):
filename =
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 ''
filename += ext
return filename
def write_file(self,path):
with open(path,'wb') as fp:
if self.file.multiple_chunks():
for chunk in self.file.chunks():
fp.write(chunk)
else:
fp.write(self.file.read())
五、站点管理
(1) 配置admin应用
django.contrib.admin
(2) 创建管理员用户
python3 manage.py createsuperuser
依次输入用户名->邮箱->密码->确认密码
(3) 汉化
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
(4) 在App/admin.py 里面注册自己的模型类
from .models import Grade,Students
#注册模型类 在后台展示
admin.site.register(Grade)
admin.site.register(Students)
(5) 配置后台页面和添加数据的展示
#配置数据的展示
class GradeAdmin(admin.ModelAdmin):
#设置显示哪些字段
list_display = ['pk','gname','gboynum','ggirlnum']
#添加搜索字段
search_fields = ['gname']
# 分⻚
list_per_page = 5
# 过滤字段‘
list_filter = ['gname']
class StudentsAdmin(admin.ModelAdmin):
list_display = ['pk','sname','ssex','sage','grade']
search_fields = ['sname']
#分⻚
list_per_page = 5
#过滤字段‘
list_filter = ['sname']
#更改添加 修改的字段属性的位置
# fields = ['sage','ssex','sname','grade','info']
fieldsets = [
("基本信息",{"fields":['sname','sage','ssex']}),
("其它信息",{'fields':['info','grade']}),
]
#字段顺序和字段分组不能同时使⽤
#注册模型类 在后台展示
admin.site.register(Grade,GradeAdmin)
admin.site.register(Students,StudentsAdmin)
(6) 关联对象
#TabularInline 横着展示添加学⽣的布局
#StackedInline 竖着展示添加学⽣的布局
# class AddStudents(admin.TabularInline):
class AddStudents(admin.StackedInline):
class AddStudents(admin.TabularInline):
model = Students #关联的模型名称
extra = 2 #添加学⽣的个数
#配置数据的展示
class GradeAdmin(admin.ModelAdmin):
inlines = [AddStudents]
(7) bool值的显示男女
def sex(self):
if self.ssex:
return '男'
else:
return '⼥'
sex.short_description =
'性别' # 给字段名称添加简介(字段的中⽂说明)
# list_display = ['pk','sname','ssex','sage','grade']
list_display = ['pk','sname',sex,'sage','grade']