Ckeditor
admin使用Ckeditor富文本编辑器
富文本编辑器有很多种,这里介绍如何使用ckeditor
- 安装ckeditor
pip install django-ckeditor
- settings配置
#settings.py
NSTALLED_APPS = [
...
'ckeditor', # 富文本编辑器
'ckeditor_uploader', # 富文本编辑器上传图片模块
...
]
- 添加ckeditor配置
#settings.py
CKEDITOR_CONFIGS = {
'default':{
'toolbar':'full', # 完整工具条
'height': 300, # 编辑高度
# 'woidth': 300, # 编辑宽度
},
}
CKEDITOR_UPLOAD_PATH = '' # 上传图片保存路径,使用了fastDFS,设置为''
- 添加ckeditor路由配置
#urls.py
urlpatterns = [
...
re_path(r'^ckeditor/', include('ckeditor_uploader.urls')),
]
- 为我们的商品SPU表种设置额外的三个字段
from ckeditor.fields import RichTextField
from ckeditor_uploader.fields import RichTextUploadingField
class Goods(BaseModel):
...
desc_detail = RichTextUploadingField(default='', verbose_name='详细介绍')
desc_pack = RichTextField(default='', verbose_name='包装信息')
desc_service = RichTextUploadingField(default='', verbose_name='售后服务')
...
- 解决ckeditor繁体中文
C:\Python37\Lib\site-packages\ckeditor\static\ckeditor\ckeditor\lang
修改其中的语言文件配置,把zh-ch文件内容复制到zh文件中即可
vue使用CKEditor富文本编辑器
- 在vue中安装CKEditor
cnpm install ckeditor/ckeditor5-build-classic
- 组件引入
CKEditor
<script>
import CKEditor from "@ckeditor/ckeditor5-build-classic";
import "@ckeditor/ckeditor5-build-classic/build/translations/zh-cn"; //中文包
</script>
- 模版标签嵌入
<template>
<div id="toolbar-container"></div> <!-- 编辑器容器 -->
<div id="editor">
<!-- <p>This is the initial editor content.</p> -->
</div>
</template>
- vue实例数据保存编辑器实例
data() {
return {
editor: null, // 编辑器实例
}
},
- 钩子函数初始化
CKEditor编辑器
mounted() {
this.initCKEditor();
},
methods: {
initCKEditor() {
CKEditor.create(document.querySelector("#editor"), {
ckfinder: {
uploadUrl: "http://127.0.0.1:8000/ck_upload/"
// 接口返回需要:包括uploaded(选项true/false),url两个字段
}
})
.then(editor => {
const toolbarContainer = document.querySelector("#toolbar-container");
toolbarContainer.appendChild(editor.ui.view.toolbar.element);
this.editor = editor; //将编辑器保存起来,用来随时获取编辑器中的内容等,执行一些操作
})
.catch(error => {
console.error(error);
});
},
}
- 在django中响应图片上传的接口
import hashlib
def md5_(filename):
m = hashlib.md5()
m.update(filename.encode())
return m.hexdigest()
# Create your views here.
def ck_upload(request):
_f = request.FILES.get('upload')
_name = md5_(_f.name) # 生成md5名
_path = os.path.join(STATICFILES_DIRS[0],_name)
with open(_path,'wb') as fp:
fp.write(_f.read())
return JsonResponse({
'uploaded':'true',
# 表示上传成功
'url': 'http://127.0.0.1:8000/static/' + _name
# 拼接上传图片的绝对访问路径
})
- 整个页面的提交,需要在vue组件template中绑定按钮点击时间
<template>
<div>
<div id="toolbar-container"></div>
<div id="editor">
</div>
<button @click="post_editor">提交</button>
</div>
</template>
post_editor的提交事件方法
ck_post() {
axios.post("http://127.0.0.1:8000/ck_post/", {
data: this.editor.getData() // 获取了编辑器的所有内容
}).then(res=>{
console.log(res.data)
})
}
- 后端接收整个富文本部分的内容
class CkPost(APIView):
def post(self,request):
ck_data = request.data.get('data')
...
return Response({'code':200})
验证码校验
- 验证码逻辑
- 客户端发起GET连接请求,并随机生成UUID,绑定图片
UUID:通用唯一识别码(Universally Unique Identifier),目的,是让分布式系统中的所有元素,都能有唯一的辨识信息,每个人都可以创建不与其它人冲突的UUID
- 服务端生成图片验证码,图片存入内存并返回到客户端
- 服务端存储源字符串到
session中,也可以存入缓存中,例memcached、redis - 客户端表单填写验证码原值
- 移出表单框时间触发异步
post请求验证,访问时,图片uuid作为属性绑定到表单属性中,作为post提交的数据一部分 - 服务端验证时通过
UUID为key,表单值为value进行图片验证码校验
图片验证码生成
利用
pillpw库进行图片验证码的生成
from PIL import Image, ImageDraw, ImageFont
def generate(request, uuid):
'''
本地图片验证码生成函数
'''
bgcolor = (random.randrange(20, 100), random.randrange(
20, 100), random.randrange(20, 100))
width = 110
height = 40
# 创建画面对象
im = Image.new('RGB', (width, height), bgcolor)
# 创建画笔对象
draw = ImageDraw.Draw(im)
# 调用画笔的point()函数绘制噪点
for i in range(0, 100):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
draw.point(xy, fill=fill)
# 定义验证码的备选值
str = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
# 随机选取4个值作为验证码
rand_str = ''
for i in range(0, 4):
rand_str += str[random.randrange(0, len(str))]
# 构造字体对象
fonts_files = os.path.join(
STATICFILES_DIRS[0], 'fonts/' + 'SourceCodePro-Bold.ttf')
font = ImageFont.truetype(fonts_files, 30)
# 构造字体颜色
fontcolor1 = (255, random.randrange(0, 255), random.randrange(0, 255))
fontcolor2 = (255, random.randrange(0, 255), random.randrange(0, 255))
fontcolor3 = (255, random.randrange(0, 255), random.randrange(0, 255))
fontcolor4 = (255, random.randrange(0, 255), random.randrange(0, 255))
# 绘制4个字
draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1)
draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2)
draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3)
draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4)
# 释放画笔
del draw
# 存入缓存,用于做进一步验证,并设置超时时间为10分组
cache.set(uuid,rand_str,60*10)
buf = io.BytesIO()
# 将图片保存在内存中,文件类型为png
im.save(buf, 'png')
# 将内存中的图片数据返回给客户端,MIME类型为图片png!
return HttpResponse(buf.getvalue(), 'image/png')
uuid生成
浏览器生成唯一标示
uuid进行图片验证码的索取
// 根据时间戳生成当前UUID值
generate_uuid: function(){
var d = new Date().getTime();
if(window.performance && typeof window.performance.now === "function"){
d += performance.now(); //use high-precision timer if available
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random()*16)%16 | 0;
d = Math.floor(d/16);
return (c =='x' ? r : (r&0x3|0x8)).toString(16);
});
return uuid;
},
Django生效Redis缓存
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"PASSWORD": "123456",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
- 使用方法就很简单了
from django.core.cache import cache
cache.set
cache.get
服务端校验通用接口
- 视图
# views.py
class ImageCodeView(APIView):
def get(self, request, generate_image_id):
'''
获取验证码
'''
return generate_image_code(request,generate_image_id)
def post(self, request,generate_image_id):
'''
验证码识别
'''
data = {}
image_code = cache.get(generate_image_id) # 获取缓存中的验证码字符
if image_code == request.data.get('image_code'):
data['code'] = 200
else:
data['code'] = 201
return Response(data)
- 路由
#urls.py
re_path('generate_image_code/(?P<generate_image_id>)[\w-]+/',views.ImageCodeView.as_view(),name='generate_image_code'),