flask使用富文本编辑器ckeditor

2023-09-21 14:59:24 浏览数 (2)

安装

首先使用pip或Pipenv等工具安装或更新:

代码语言:javascript复制
$ pip install -U flask-ckeditor

初始化扩展

一般情况下,你只需要导入并实例化CKEditor类,并传入程序实例即可:

代码语言:javascript复制
from flask_ckeditor import CKEditor

app = Flask(__name__)
ckeditor = CKEditor(app)

如果你使用了工厂函数,那么也可以调用init_app()方法来进行初始化:

代码语言:javascript复制
from flask_ckeditor import CKEditor

ckeditor = CKEditor()

def create_app():
    app = Flask(__name__)
    ckeditor.init_app(app)
    return app

引入CKEditor资源

为了使用CKEditor,我们首先要在模板中引入CKEditor的JavaScript等资源文件。推荐的做法是自己编写资源引用语句,你可以在CKEditor提供的Online Builder构建一个自定义的资源包,下载解压后放到项目的static目录下, 并引入资源包内的ckeditor.js文件,比如(实际路径按需调整):

代码语言:javascript复制
<script src="{{ url_for('static', filename='ckeditor/ckeditor.js') }}"></script>

如果你不需要自定义,那么也可以从CDN加载:

代码语言:javascript复制
<script src="//cdn.ckeditor.com/4.9.2/standard/ckeditor.js"></script>

最后,作为替代选项,你也可以使用Flask-CKEditor提供的ckeditor.load()方法来生成引用语句:

代码语言:javascript复制
{{ ckeditor.load() }}

它默认从CDN加载资源,将配置变量CKEDITOR_SERVE_LOCAL设为True会使用扩展内置的本地资源。另外,你也可以使用custom_url参数来使用自定义资源包:

代码语言:javascript复制
{{ ckeditor.load(custom_url=url_for('static', filename='ckeditor/ckeditor.js')) }}

创建CKEditor文本区域

Flask-CKEditor提供了两种方式来CKEditor文本区域:

1. 与WTForms/Flask-WTF集成

Flask-CKEditor提供了一个CKEditorField字段类,和你平时从WTForms导入的StringField、SubmitField用法相同。事实上,它就是对WTForms提供的TextAreaField进行了包装。

作为示例,我们可以创建一个写文章的表单类。这个表单类包含一个标题字段(StringField),一个正文字段(CKEditorField)和一个提交字段(SubmitField)。你会看到,其中的正文字段使用了CKEditorField。

代码语言:javascript复制
from flask_wtf import FlaskForm
from flask_ckeditor import CKEditorField
from wtforms import StringField, SubmitField

class PostForm(FlaskForm):
    title = StringField('Title')
    body = CKEditorField('Body')
    submit = SubmitField('Submit')

在渲染文本编辑区域的模板中,我们可以像往常一样渲染表单:

代码语言:javascript复制
<form method="post">
    {{ form.title.label }}{{ form.title() }}
    {{ form.body.label }}{{ form.body() }}
    {{ form.submit() }}
</form>

{{ ckeditor.load() }}
{{ ckeditor.config(name='body') }}

唯一需要注意的是,我们需要在资源引用语句后调用ckeditor.config()方法来让对CKEditor进行配置和初始化,并将name参数的值设为CKEditor字段的属性名,这里即body。

当表单提交后,你可以像其他字段一样通过form.attr.data属性来获取数据,这里的文本区域数据即form.body.data。

2. 手动创建

如果你不使用WTForms/Flask-WTF,那么可以直接使用Flask-CKEditor提供的ckeditor.create()方法在模板中创建文本编辑区域:

代码语言:javascript复制
<form method="post">
    {{ ckeditor.create() }}
    <input type="submit">
</form>

{{ ckeditor.load() }}
{{ ckeditor.config() }}  <!-- 这时不用设置name参数 -->

在表单被提交后,你可以使用ckeditor作为键从表单数据中获取对应的值,即request.form.get('ckeditor')。

图片上传

在使用文本编辑器写文章时,上传图片是一个很常见的需求。在CKEditor中,图片上传可以通过File Browser插件实现。在服务器端的Flask程序中,你需要做三件事:

  1. 创建一个视图函数来处理并保存上传文件
  2. 创建一个视图函数来获取图片文件,类似Flask内置的static端点
  3. 将配置变量CKEDITOR_FILE_UPLOADER设为这个视图函数的URL或端点值

完整的代码示例如下所示:

代码语言:javascript复制
from flask_ckeditor import upload_success, upload_fail

app.config['CKEDITOR_FILE_UPLOADER'] = 'upload'

@app.route('/files/<path:filename>')
def uploaded_files(filename):
    path = '/the/uploaded/directory'
    return send_from_directory(path, filename)

@app.route('/upload', methods=['POST'])
def upload():
    f = request.files.get('upload')  # 获取上传图片文件对象
    # Add more validations here
    extension = f.filename.split('.')[1].lower()
    if extension not in ['jpg', 'gif', 'png', 'jpeg']:  # 验证文件类型示例
        return upload_fail(message='Image only!')  # 返回upload_fail调用
    f.save(os.path.join('/the/uploaded/directory', f.filename))
    url = url_for('uploaded_files', filename=f.filename)
    return upload_success(url=url) # 返回upload_success调用

注意 传入request.files.get()的键必须为'upload', 这是CKEditor定义的上传字段name值。

在处理上传文件的视图函数中,你必须返回upload_success()调用,每将url参数设置为获取上传文件的URL。通常情况下,除了保存文件,你还需要对上传的图片进行验证和处理(大小、格式、文件名处理等等,具体可以访问这篇《Flask文件上传(一):原生实现》了解),在验证未通过时,你需要返回upload_fail()调用,并使用message参数传入错误消息。

当设置了CKEDITOR_FILE_UPLOADER配置变量后,你可以在编辑区域点开图片按钮打开的弹窗中看到一个新的上传标签。另外,你也可以直接将图片文件拖拽到编辑区域进行上传,或复制文件并粘贴到文本区域进行上传(CKEditor >= 4.5)。

如果你使用的 CKEditor 版本小于 4.5,则使用下面的方式实现:

代码语言:javascript复制
from flask import send_from_directory

app.config['CKEDITOR_FILE_UPLOADER'] = 'upload'  # this value can be endpoint or url

@app.route('/files/<filename>')
def uploaded_files(filename):
    path = '/the/uploaded/directory'
    return send_from_directory(path, filename)

@app.route('/upload', methods=['POST'])
@ckeditor.uploader
def upload():
    f = request.files.get('upload')
    f.save(os.path.join('/the/uploaded/directory', f.filename))
    url = url_for('uploaded_files', filename=f.filename)
    return url

为图片上传请求添加 CSRF 保护

如果你想为图片上传的请求添加 CSRF 保护,可以通过 CSRFProtect 实现(Flask-WTF 内置),首先安装 Flask-WTF:

代码语言:javascript复制
$ pip install flask-wtf

然后初始化扩展:

代码语言:javascript复制
from flask_wtf import CSRFProtect

csrf = CSRFProtect(app) 

Flask-CKEditor 0.4.3 版本内置了对 CSRFProtect 的支持,当使用 CSRFProtect 时,只需要把配置变量 `CKEDITOR_ENABLE_CSRF` 设为 `True` 即可开启 CSRF 保护:

代码语言:javascript复制
app.config['CKEDITOR_ENABLE_CSRF'] = True

顺便说一句,在 Flask-CKEditor 内部需要把 CSRF 令牌放到上传图片的 AJAX 请求首部,这通过 CKEditor 4.9.0 版本新添加的一个配置选项 fileTools_requestHeaders 实现,这个配置可以用来想文件上传请求插入自定义的首部字段 。所以,如果想要实现 CSRF 保护,CKEditor 的版本需要大于或等于 4.9.0。

代码语法高亮

代码语法高亮可以通过Code Snippet插件实现(基于hightlight.js),你可以将配置变量CKEDITOR_ENABLE_CODESNIPPET设为Ture来开启。在此之前,你需要确保安装了这个插件(内置的资源包包含了这个插件)。

为了正确渲染代码块,你还需要引入对应的资源文件,最简单的方式是使用Flask-CKEditor提供的ckeditor.load_code_theme()方法:

代码语言:javascript复制
<head>
 ...
 {{ ckeditor.load_code_theme() }}
</head>

你可以通过配置变量CKEDITOR_CODE_THEME来设置语法高亮的主题,默认为monokai_sublime,你可以在这个页面看到所有可用的主题对应的字符串。

语法高亮示例

提示 对应的示例程序在examples/codesnippet/目录下。

使用示例程序

项目仓库中提供了5个示例程序,分别展示基本用法、图片上传插入、代码语法高亮、Markdown模式和不使用Flask-WTF/WTForms。以基本示例程序为例,你可以通过下面的命令来获取并运行它:

代码语言:javascript复制
$ git clone https://github.com/greyli/flask-ckeditor
$ cd flask-ckeditor/examples
$ pip install -r requirements.txt
$ python basic/app.py

然后在浏览器访问http://127.0.0.1:5000。

另外,helloflask仓库里在demos/form目录下的示例程序也包含一个Flask-CKEditor使用示例。

相关链接

  • GitHub:https://github.com/greyli/flask-ckeditor
  • PyPI:https://pypi.python.org/pypi/Flask-CKEditor

参考https://zhuanlan.zhihu.com/p/38643309

0 人点赞