专栏首页菲宇flask使用富文本编辑器ckeditor

flask使用富文本编辑器ckeditor

安装

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

$ pip install -U 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')。

图片上传

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

  1. 创建一个视图函数来处理并保存上传文件
  2. 创建一个视图函数来获取图片文件,类似Flask内置的static端点
  3. 将配置变量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)。

如果你使用的 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

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

相关链接

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从零搭建一个自动化运维体系

    DevOps的出现有其必然性。在软件开发生命周期中,遇到了两次瓶颈。第一次瓶颈是在需求阶段和开发阶段之间,针对不断变化的需求,对软件开发者提出了高要求,后来出现...

    菲宇
  • 微服务部署:蓝绿部署、滚动部署、灰度发布、金丝雀发布

    目前有很多用于部署的技术,有的简单,有的复杂;有的得停机,有的不需要停机即可完成部署。本文的目的就是将目前常用的布署方案做一个总结。

    菲宇
  • Docker监控——Cadvisor+InfluxDB+Grafana搭建

    对于一个物理机上运行多个容器应用时,容器的运行情况如:CPU使用率、内存使用率、网络状态、磁盘空间等信息,都是需要去了解的,因此监控是必须的。对于容器的监控方案...

    菲宇
  • Autopilot浮现 微软的云计算密钥

    作为微软首席执行官,萨蒂亚·纳德拉可能还是位初来乍到的新人,但他对于该公司的关键性内部工具以及与Amazon及谷歌开展竞争的方案早已非常熟稔:这正是名为Auto...

    静一
  • AngularDart Material Design 输入 顶

    Selector: <material-input:not(material-input[multiline])>

    南郭先生
  • 如何写出漂亮的代码?写代码应该遵守的原则和规范

    这里的“orderId”字符串就称之为魔法字符串,其实很容易写错。而且假如以后这个参数改个名字叫:movieOrderId,那这些字符串就得改很多处,而且不能通...

    lyb-geek
  • MySQL用户权限的手册

    挨踢小子部落阁
  • 腾讯“互联网+汽车”来了

    腾讯与传统汽车厂商的合作正在加速,近日宝马QQ上线,装载了BMW互联驾驶的车主,就可以通过宝马聊QQ,这也是全球第一款车载集成即时通讯的社交应用。 据了解,搭载...

    腾讯研究院
  • 在机器学习模型运行时保持高效的方法

    用户1737318
  • 程序员发展必经的四个阶段,你在第几个?

    这个阶段往往是小白阶段,要么经验积累不够(比如刚毕业),要么是重大技术转型阶段(颠覆性的,比如由GUI应用模式转到Web应用模式).

    技术zhai

扫码关注云+社区

领取腾讯云代金券