Flask CKEditor 5 富文本编辑器

1. CKEditor5 基本使用

官方有三种下载方式Command line,Zip package,CDN
我下的是Zip文件
在这里插入图片描述
编辑器支持多种语言
需要用到的是ckeditor.js,translations/zh-cn.js,sample/css/sample.css
sample.css是官方提供的,可以自己设置
创建一个flask项目
Flask CKEditor 5 富文本编辑器_第1张图片
ckeditor5.html是编辑器页面,效果是这样的
Flask CKEditor 5 富文本编辑器_第2张图片


<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设置下拉框内容
Flask CKEditor 5 富文本编辑器_第3张图片
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还能安装许多插件

2. Flask后端处理

图片上传

上传图片用的是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

你可能感兴趣的:(Flask CKEditor 5 富文本编辑器)