富文本编辑器即WYSIWYG(What You See Is What You Get)编辑器(所见即所得编辑器)。在Web程序中可用的开源富文本编辑器中,CKEditor是一个流行的选择。Flask-CKEditor简化了将CKEditor集成到Flask项目中的过程,可以让你方便的在Flask项目中添加富文本编辑器。它包含下面这些特性:
- 提供WTForms/Flask-WTF集成支持
- 支持图片上传与插入
- 通过Flask配置来设置编辑器的语言、高度等参数
- 支持代码块语法高亮
《Flask Web开发实战》中的第2个示例程序(博客程序Bluelog)使用了这个扩展。
基本用法
安装
首先使用pip或Pipenv等工具安装:
$ pip install flask-ckeditor
初始化扩展
一般情况下,你只需要导入并实例化CKEditor类,并传入程序实例即可:
from flask_ckeditor import CKEditor app = Flask(__name__) ckeditor = CKEditor(app)
如果你使用了工厂函数,那么也可以调用init_app()方法来进行初始化:
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文件,比如(实际路径按需调整):
<script src="{{ url_for('static', filename='ckeditor/ckeditor.js') }}"></script>
如果你不需要自定义,那么也可以从CDN加载:
<script src="//cdn.ckeditor.com/4.9.2/standard/ckeditor.js"></script>
最后,作为替代选项,你也可以使用Flask-CKEditor提供的ckeditor.load()方法来生成引用语句:
{{ ckeditor.load() }}
它默认从CDN加载资源,将配置变量CKEDITOR_SERVE_LOCAL设为True会使用扩展内置的本地资源。另外,你也可以使用custom_url参数来使用自定义资源包:
{{ 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。
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')
在渲染文本编辑区域的模板中,我们可以像往常一样渲染表单:
<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()方法在模板中创建文本编辑区域:
<form method="post"> {{ ckeditor.create() }} <input type="submit"> </form> {{ ckeditor.load() }} {{ ckeditor.config() }} <!-- 这时不用设置name参数 -->
在表单被提交后,你可以使用ckeditor作为键从表单数据中获取对应的值,即request.form.get('ckeditor')。
提示 完整的示例程序在examples/basic/和examples/without-flask-wtf目录下。
配置变量
Flask-CKEditor提供了下面这些配置变量:
配置 | 默认值 | 说明 |
---|---|---|
CKEDITOR_SERVE_LOCAL
|
False
|
使用内置的ckeditor.load()方法时,设置是否使用本地资源,默认从CDN加载 |
CKEDITOR_PKG_TYPE
|
'standard'
|
CKEditor资源包的类型,basic、 standard和 full 中的一个
|
CKEDITOR_LANGUAGE
|
None
|
设置CKEditor文本编辑器的语言,默认会自动探测用户浏览器语言,所以一般不需要设置。你也可以设置ISO 639格式的语言码,比如zh、 en 、jp等
|
CKEDITOR_HEIGHT
|
CKEditor默认 | 编辑器高度,单位为px |
CKEDITOR_WIDTH
|
CKEditor默认 | 编辑器宽度,单位为px |
CKEDITOR_FILE_UPLOADER
|
None
|
处理上传文件的URL或端点 |
CKEDITOR_FILE_BROWSER
|
None
|
处理文件浏览的URL或端点 |
CKEDITOR_ENABLE_MARKDOWN
|
False
|
设置是否开启markdown插件,需要安装对应插件 |
CKEDITOR_ENABLE_CODESNIPPET
|
False
|
设置是否开启codesnippet插件(插入代码块),需要安装对应插件 |
CKEDITOR_CODE_THEME
|
'monokai_sublime'
|
当使用codesnippet插件时,设置语法高亮的主题 |
CKEDITOR_EXTRA_PLUGINS
|
[]
|
在CKEditor中开启的额外扩展列表,对应的扩展需要被安装 |
图片上传
在使用文本编辑器写文章时,上传图片是一个很常见的需求。在CKEditor中,图片上传可以通过File Browser插件实现。在服务器端的Flask程序中,你需要做三件事:
- 创建一个视图函数来处理并保存上传文件
- 创建一个视图函数来获取图片文件,类似Flask内置的static端点
- 将配置变量CKEDITOR_FILE_UPLOADER设为这个视图函数的URL或端点值
完整的代码示例如下所示:
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)。
提示 对应的示例程序在examples/image-upload/目录下。
如果你使用的 CKEditor 版本小于 4.5,则使用下面的方式实现:
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:
$ pip install flask-wtf
然后初始化扩展:
from flask_wtf import CSRFProtect csrf = CSRFProtect(app)
Flask-CKEditor 0.4.3 版本内置了对 CSRFProtect 的支持,当使用 CSRFProtect 时,只需要把配置变量 `CKEDITOR_ENABLE_CSRF` 设为 `True` 即可开启 CSRF 保护:
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()方法:
<head> ... {{ ckeditor.load_code_theme() }} </head>
你可以通过配置变量CKEDITOR_CODE_THEME来设置语法高亮的主题,默认为monokai_sublime,你可以在这个页面看到所有可用的主题对应的字符串。
提示 对应的示例程序在examples/codesnippet/目录下。
使用示例程序
项目仓库中提供了5个示例程序,分别展示基本用法、图片上传插入、代码语法高亮、Markdown模式和不使用Flask-WTF/WTForms。以基本示例程序为例,你可以通过下面的命令来获取并运行它:
$ 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。
相关链接
如何在文章中的每个代码段,添加一键复制按钮?
看看这个项目 https://clipboardjs.com/
您好,请问一下,在使用Flask-CKEditor上传图片的时候,目前发现在上传标签页中,只有“选择文件”和“上传服务器”的两个按钮。是否有选择目标文件夹的功能呢?比如选择一个文件后,想把这个文件放到不同的目标文件夹下,方便管理。如果有这个功能,是需要设置什么条件才能显示出来呢?如果暂时没有这个功能,是否有什么思路可以提供参考呢?谢谢!!
单独安装flask_ckeditor时,在工厂函数使用时页面报错,提示未安装WTForm模块,用pip安装flask_wtf后才能正常使用。
请问,cheditor在modal框上,下拉框闪一下就 没有了,怎么解决呀?
可以把问题详细信息发到 HelloFlask 论坛。
博主你好
我在ckeditor编辑好的文章显示时发现格式就与编辑时不一样,请问有什么解决办法吗。具体就是图片的问题,比如上传了一张图图片显示在左侧,但是显示文章的时候,图片的大小位置都跟编辑时候不一样。用的是你的ckeditor教程里的image-upload。
麻烦提供下上传图片以后生成的源码。另外建议在网站添加一些全局的 CSS 对图片添加一些限定。
博主你好,问题已经解决,是CSS的问题。但是现在不太满足于ckeditor的默认的图片上传方式,想改用easyimage那种简单好用的图片上传方式。按照你的博文所述,发现改用easyimage之后,图片可以上传到本地服务器,但是生成的文章的html中图片的链接却不对
。如果用ckeditor默认的图片上传扩展的话,图片链接就是没有问题的。请问这有办法解决吗。easyimage上传图片我觉得操作上友好很多。
链接不对是指什么?你需要给出你期望的链接和现在的错误链接。
我用easyimage上传一张图片之后产生的语句如下
(figure class=”easyimage easyimage-full”/)
(img alt=”” src=”blob:http://127.0.0.1:5000/d67282b6-290c-465f-9e74-4e52718f4ad1” width=”1920″ /)
(figcaption)(/figcaption)
(/figure)
然后下次再显示文章,图片就没了。
我把<改成(了,不然好像发不出来
如果不用easyimage而用ckeditor的standard的扩展,图片的链接形式就是像下面这样
src="/files/users/picture.png"。
这样文章就能正常显示图片。
但我觉得easyimage处理图片的方式友好很多,我想用easyimage.
我看了下,easyimage 是把图片上传到 CKEditor 的 CDN 服务器上的,所以地址应该类似 https://33333.cdn.cke-cs.com/rc1DFuFpHqcR3Mah6y0e/images/f32e…8163a.png。用这个扩展的话不需要任何相关的配置,包括处理上传的视图函数和相关配置都需要删掉。
为什么使用ckeditor后validate_on_submit()总是返回False
可以在视图函数的 return 语句前加一行 print(form.errors) 看看是哪个字段没通过验证。
帮了大忙
code snippet 怎么设置?
我按照你的说明 不好用
是使用内置的 CKEditor 资源吗?「不好用」具体是指什么?
请问这里那里有错误
config:
CKEDITOR_SERVE_LOCAL = True # 加载本地ckeditor
CKEDITOR_PKG_TYPE = ‘full’
CKEDITOR_ENABLE_CODESNIPPET = True
html :
{{ form.csrf_token }}
{{ form.title.label() }}
{{ form.title(class=’form-control’) }}
{%for err in form.title.errors%}
{{err}}
{% endfor %}
{{ form.article.label(style=’font-size:16px’) }}
{# 显示博客输入内容#}
{{ form.article() }}
{{ ckeditor.load() }}
{{ ckeditor.config() }}
{%for err in form.article.errors%}
{{err}}
{% endfor %}
发表
试试把调用 config 那一行改成:{{ ckeditor.config(name=’article’) }}
你好,我想在flask-ckeditor 扩展下 给ckeditor 安装别的插件应该如何配置?
在 CKEditor 网站下载扩展,放到扩展文件夹,然后在把配置 CKEDITOR_EXTRA_PLUGINS 定义为列表,包含扩展名称。
你好,我下载完整版的ckeditor包加到static文件夹下,编辑文章的时候ckeditor还是没有完整的插件,我在settings.py中添加CKEDITOR_PKG_TYPE = ‘full’没有用,我按照网上搜索的教程修改ckeditor文件夹下的config.js也没有效果。
当我设置CKEDITOR_SERVE_LOCAL = True,并且在edit_post.html中添加{{ ckeditor.load(pkg_type=”full”) }}时就可以显示所有插件。我想显示所有插件,如果我从本地加载而不是从CDN加载ckeditor时要怎么做呢?
请问在编辑的内容里面如何引入自定义的css和js文件?
另外Flask-ckediter如何使用ckediter其他的配置变量?例如下面列举的这些:
https://blog.csdn.net/qq_38834352/article/details/81219494
谢谢!!
请问flask-ckeditor怎么拿到数据的时候去掉html标签,就是通过表单获取数据,是带html标签的,而且jinja统计字数也会算上标签=
可以用 bleach 之类的工具清除 HTML 标签。如果只是为了统计正确的字数,可以用 Jinja2 内置的 striptags 过滤器。
已经想到用爬虫库清理标签了=,顺便统计了字数,用striptags过滤标签来统计字数应该更方便
在手动创建这里:
{{ ckeditor.create() }}
请问如何设置默认值,比如说数据库中以前的内容要再次编辑就让以前的内容作为默认值加载到这里,请问如何实现?
谢谢
{{ ckeditor.create(value=’默认值’) }} 没记错的话,应该是这样,可以试一下。
确实是这样,因为我是用的从后端传过来的变量,所以是用的{{ ckeditor.create(value=default) }}形式。
谢谢!!
我真想给你点赞!
请问一下,flask-ckeditor4.9版本,配合flask-admin使用,是不能用blueprint.route的吗
信息太少,没法判断,麻烦把问题详情和相关代码发到 HelloFlask 论坛。
我感觉现在的ckeditor存在一些问题,如果能对应几个比较合适的bootstrap的img相关的标签就好了。
请问作者,我在代码中用到了一个ckeditor的插件image2,但是一直请求不到。我先是在官网上进行了定制,后来发现不行,又手动下载的那个插件,并解压到了plugins文件夹下,不过还是请求不到;
而且每个请求后面还有一个参数t=I3I8。
不太明白是哪里出了问题
你好,如果方便的话,可以在 GitHub 项目创建 issue,附上尝试的操作步骤和相关代码。
你好,使用flask-ckeditor和wtforms以及flask-wtf的话,如何升级ckeditor5呢,我尝试了直接更换资源包以及从SDN加载ckeditor5都不成功呢。但是ckeditor4是可以的,请问如果是ckeditor5的话该怎么配置呢?
你好,CKEditor 5 的使用方式和 4 不一样,Flask-CKEditor 目前只支持 CKEditor 4。你可以参考 Flask-CKEditor 的代码和 CKEditor 5 的文档自己写集成代码,或者等我有时间为 Flask-CKEditor 添加对 5 的支持。
你好!按照教程使用flask-ckeditor插件。怎样将编辑器语言设置为简体中文?已经在ckeditor网站自定义下载了简体中文语言包,页面展示默认的仍然是英文。
是不是浏览器把语言偏好设成了英文?默认是自动根据浏览器设置来更新语言的。
你好,关于最新升级的3.0版本,其中我最想要那个图片上传功能,有几行代码我不知道在哪加,我是按狗书那个结构写的,其中
ckeditor = CKEditor(app),这句代码应该加在哪?init.py中吗?还是manage.py?还有
app.config[CKEDITOR_FILE_UPLOADER]=‘upload’,这句我感觉要加到config里,但是调试了好半天,都出不来upload那个选项
实例化扩展类可以放到程序包的__init__.py里,和其他扩展的实例化语言放在一起。配置的问题已经回复邮件给你了。另外,请使用pip install -U flask-ckeditor升级到0.3.1版本。
博主你好,请教一下,这个没有代码高亮的吗,而且这个编辑器貌似也不安全吧,直接用safe过滤器避免转义,这会导致xss攻击?代码高亮能给个思路吗
代码高亮可以在服务器端使用Pygemnts处理,但使用CKEditor社区的code snippet等扩展比较方便。下周我会发布0.3版本,新版本会包含一个本地js包,会内置代码高亮,图片上传等功能。另外也会支持加载自定义资源。
关于XXS,编辑器自身有基本的保护机制,你可以测试一下。如果你想做到绝对安全,可以再服务器端再对数据进行二次清理,比如使用Blench。
请问开启Flask-CKeditor图片CSRF的保护功能后 将CSRF_Token的值传进请求头中,这边上传图片一直报The CSRF token is missing
Flask-CKEditor 需要升级到最新版本,同时使用 CSRFProtect 扩展开启 CSRF 保护,具体参考这篇文章最后一节。