官方有三种下载方式Command line,Zip package,CDN
我下的是Zip文件
编辑器支持多种语言
需要用到的是ckeditor.js,translations/zh-cn.js,sample/css/sample.css
sample.css是官方提供的,可以自己设置
创建一个flask项目
ckeditor5.html是编辑器页面,效果是这样的
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link type="text/css" href="../static/sample.css" rel="stylesheet" media="screen" />
<title>Titletitle>
head>
<body>
<main>
<form action="/edit" method="post" class="centered">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<textarea name="content" id="editor">
textarea>
<p><input type="submit" value="提交">p>
form>
main>
<script src="../static/ckeditor.js">script>
<script src="../static/zh-cn.js">script>
<script>
ClassicEditor
.create( document.querySelector('#editor'), {
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'imageUpload', '|', 'undo', 'redo'],
heading: {
options: [
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
{ model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' }
]
},
ckfinder: {
uploadUrl: "http://127.0.0.1:5000/img"
},
language: 'zh-cn'
})
.then( editor => {
console.log(editor);
})
.catch( error => {
console.error(error);
})
script>
body>
html>
textarea标签为编辑器,id设置为editor在下面script里用到了
在form里设置一个按钮,上传数据
toolbar设置工具栏
heading设置下拉框内容
ckfinder设置上传图片的链接
language设置语言,需要引入js
<script src="../static/zh-cn.js">script>
CKEditor5默认的工具有下列
"undo", # 撤销
"redo", # 重做
"bold", # 加粗
"link", # 链接
"italic", # 斜体
"heading", # 标题
"blockQuote", # 块引用
"imageUpload", # 插入图片 class="image"
"numberedList", # 有序列表
"bulletedList", # 无序列表
"imageStyle:full", # 图片与上下文组合方式:图片占一整行
"imageStyle:side", # 图片与上下文组合方式:图片在文字的旁边 class="image-style-side"
"imageTextAlternative" # 用于图片加载不出来时替换显示的文字
还有其他工具可以去官方文档找,CKEditor5还能安装许多插件
上传图片用的是CKEditor框架自带的上传功能,自带csrf,如果用了Flask的CSRFProtect
一定要在视图函数前加上@csrf.exempt让这个视图函数不受csrf保护
不然会一直上传图片失败
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)
@csrf.exempt
@app.route('/img', methods=['POST'])
@login_required
def img_load():
file = request.files['upload']
suffix = file.filename.rsplit('.', 1)[1]
if suffix not in ('jpeg', 'jpg', 'png', 'gif'):
response = {
'uploaded': False,
'url': '/'
}
return jsonify(response)
name = uuid.uuid4().hex + '.' + suffix
while os.path.exists(os.path.join(os.getcwd(), 'static', name)):
name = uuid.uuid4().hex + '.' + suffix
file.save(os.path.join(os.getcwd(), 'static', name))
response = {
'uploaded': True,
'url': 'imgs/' + name
}
return jsonify(response)
路由地址跟html里设置的uploadUrl对应
通过request获取图片文件
file = request.files['upload']
这个视图函数需要返回一个json对象
用的是flask里面的jsonify
from flask import jsonify
先检测后缀
然后用uuid4给图片一个随机名
保存在服务器里
如果上传失败返回的json对象里的uploaded为False,url随意
上传成功返回True,url填图片地址
编辑器得到这个回应后会访问url来获取图片,得到服务器里的图片
下面是返回图片的函数
@app.route('/imgs/' )
@login_required
def load(img_name):
image = os.path.join(os.getcwd(), 'static', img_name)
if not os.path.exists(image):
return redirect('page_not_found')
suffix = {
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'png': 'image/png',
'gif': 'image/gif'
}
mine = suffix[str(image.rsplit('.', 1)[1])]
with open(image, 'rb') as file:
img = file.read()
return Response(img, mimetype=mine)
路由地址和url对应,‘url’: ‘imgs/’ + name
得到图片名字,获得图片保存路径,如果图片不存在返回404
图片存在就返回图片
这里用到了Response
from flask import Response
把后缀转换为Response需要的MINE类型,读取文件,return这张图片
编辑器就会显示这张图片,代表上传成功
接收编辑器提交的内容
<form action="/edit" method="post" class="centered">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<textarea name="content" id="editor">
textarea>
<p><input type="submit" value="提交">p>
form>
@app.route('/edit', methods=['POST'])
@login_required
def ck_editor():
form = request.form.get('content')
if not form:
return redirect(url_for('editor'))
article = Article()
article.author_id = g.user.user_id
db.session.add(article)
db.session.commit()
with open(os.path.join(os.getcwd(), 'templates', 'template.html'), 'r') as file:
html = file.read()
with open(os.path.join(os.getcwd(), 'templates', str(article.article_id) + '.html'), 'w') as file:
file.write(html.format(form))
return redirect('/' + str(article.article_id))
拿到form表单里textarea的内容
如果是空的就返回到编辑器页面
如果不是空的
记录文章作者的id,上传到数据库,这里也可以直接把文章上传到数据库
我是为文章生成一个html文件保存
下面两个with
一个是读取模板,把内容写入,html里面有一个{},用format把form填入
<body>
<div>
{}
div>
body>
一个是保存html文件
最后重定向到新生成的页面
新生成的html里面要根据编辑器提交的标签设置好css