为Flask编写1个百度编辑器的插件

原文地址:javascript

http://52sox.com/write-a-flask-plugin-for-ueditor/php

近期项目开发中,隔壁那个搞python的哥们居然笑着对我说,但愿我能给他写1个百度编辑器的demo,方便他直接调用。
当时真的受宠若惊,这哥们实力不在我之下,只能答应它了。上网搜索下,有1篇文章Flask项目集成富文本编辑器UEditor实现图片上传功能已经有1个现成的例子了。
这篇文章的做者,直接在视图中定义对应的操做,进行一系列图片上传功能的。可是,这并无知足个人要求,我想要的想过是直接导入一个模块,而后它帮我作完一切的事情。好比这样的形式:html

from xxx import yyy

app = Flask(__name__)
yyy(app)

因而只好从头开始学习。
这里,我按照以下的方式从头编写1个Flask版本的百度编辑器的插件:前端

  • 百度文档的解读java

  • 后端实际代码的编写python

  • 前端代码的编写git

下面咱们开始咱们编写插件的过程。github

百度文档的解读

在百度文档中,已经说明UEditor提供4种后台语言,分别为php,asp,asp.net和jsp。首先须要配置serverUrl参数,当ueditor初始化会向serverUrl中的URL发起对后端配置的请求。
而配置的优先级以下:json

后端获取的配置项 > 实例化传入的配置项 > ueditor.config.js文件的配置项

能够看到,后端获取的配置项优先级是最高的。在对后端配置请求的过程当中,会对配置文件config.json中的设置进行读取。
而在请求的过程当中,百度文档统一请求格式说明中已经说明,经过GET请求上的action参数来判断是什么类型的请求。后端根据不一样的请求,进行对应的处理后,须要返回给定格式的内容给前端Javascript。返回的结果通常为JSON的形式。flask

实现目标

如今咱们已经对百度编辑器UEditor的文档进行了初步的解读,下面咱们开始编写咱们实际的代码。
在这里,咱们主要会用到config和uploadimage这2个配置,其余功能留给读者本身去实现。

实际代码的编写

在编写代码以前,我打算这样来实现这个插件:

  • 配置文件为1个python的模块

  • 有1个模块用于处理对应请求的操做

  • 有1个模块用于处理图片上传的操做,这里直接拿取以前Flask文档做者中的上传模块

而后咱们逐一进行讲解。

配置文件

这里,我打算将百度默认提供的配置写入到1个config的模块中,原本打算使用相似以下的方式:

imageAction = "uploadimage"
imageFieldName = "upfile"
...

因为时间比较紧,一时半会作不到Flask中读取配置文件后为1个字典的形式,所以简化为该模块直接返回1个字典,以下所示:

CONFIG = dict(imageActionName = "uploadimage", # 执行上传图片的action名称
              imageFieldName = "upfile",       #提交的图片表单名称
              imageMaxSize = 2048000,         #上传大小限制,单位B
              imageAllowFiles = ['.png', '.jpg', '.jpeg', '.gif', '.bmp'], #上传图片格式显示
              imageCompressEnable = True,      #是否压缩图片,默认是true
              imageCompressBorder = 1600,      #图片压缩最长边限制
              imageInsertAlign = "none",      #插入的图片浮动方式
              imageUrlPrefix = "",             #图片访问路径前缀
              imagePathFormat = "upload/{yyyy}/{mm}/{dd}/{time}{rand:6}"              
              )

咱们将这段代码定义为config模块中,这样,咱们就完成了配置模块的内容了。

处理请求

这里咱们定义1个ueditor的模块用于咱们处理请求的操做。这里,我定义了1个UEditor的类用于处理这个操做:

class UEditor(object):
    pass

首先咱们要作的第一步是解决请求参数的问题,让不一样的请求调用不一样的处理函数,咱们将其定义在该类的get_action函数中:

def get_action(self):
        action = request.args.get('action')
        if action:
            return self.handle(action)

咱们将具体处理的过程放在handle函数中,在这个函数中,咱们要作2件事情:

  1. 根据不一样的请求参数调用不一样的函数

  2. 将不一样函数返回的结果返回给调用者

而后是handle函数其具体的源码:

def handle(self, action):
        if action == 'config':
            result = get_config()
        elif action == 'uploadimage':
            result = upload_image()
        else:
            result = {'state': '未实现'}
        res = make_response(json.dumps(result))
        res.headers['Access-Control-Allow-Origin'] = '*'
        res.headers['Access-Control-Allow-Headers'] = 'X-Requested-With,X_Requested_With'
        return res

能够看到,这部分的源码和咱们以前编写的并无什么不一样。在action时咱们应该将配置文件中的内容直接返回便可:

def get_config():
    return CONFIG

而在上传图片的时候,咱们根据配置文件中的配置,将其传递给上传文件的模块,这里咱们直接把以前Flask那篇文章做者git上的Uploader拿了过来。其实他也是参考php的实现的源码,将其修改成python版本而言。

def upload_image():
    """上传图片"""
    fieldName = CONFIG.get('imageFieldName')
    conf = dict(pathFormat = CONFIG.get('imagePathFormat'),
                maxSize = CONFIG.get('imageMaxSize'),
                allowFiles = CONFIG.get('imageAllowFiles')
                )
    if request.files.get(fieldName):
        field = request.files[fieldName]
        uploader = Uploader(field, conf, 'static')
        result = uploader.getFileInfo()
    else:
        result = {'state': '上传接口出错'}
    return result

这里,在Uploader类中第1个参数为类文件对象,第2个参数为对应的配置,第3个参数为图片上传的根目录。最后,经过这个实例的getFileInfo方法获得后端上传成功后返回的内容。
这样,咱们就基本解决了后端图片上传的过程了。可是,前端的调用问题咱们彻底尚未涉及到,下面咱们来讲说前端的调用问题。

前端调用

关于前端调用的问题,我我的的设想是在1个模板文件中咱们引入百度UEditor对应的Javascript文件,而后咱们初始化对应的对象后,设置serverUrl为咱们给定的URL地址便可操做了。通常咱们的代码是这样的:

<script type="text/javascript" charset="utf-8" src="static/ueditor.config.js"></script>
<script type="text/javascript" charset="utf-8" src="static/ueditor.all.min.js"> </script>
<script type="text/javascript" charset="utf-8" src="static/lang/zh-cn/zh-cn.js"></script>

<div>
    <div id="editor" style="height:400px;"></div>
</div>

<script type="text/javascript">
    var ue = UE.getEditor('editor', {
        serverUrl: "xxxx/yyyyy"
    });
</script>

以前咱们后端代码的过程只解决了图片上传的问题,关于serverUrl关联到对应URL的问题还一直没有解决。
为了解决这个问题,我打算引入蓝图和Flask提供的add_url_rule来解决这个问题。

UE = Blueprint('ueditor', __name__, url_prefix= '/ueditor')

...

def init_app(self,app):
    self.app = app
    UE.add_url_rule('/upload/'
                   'uploads',
                   self.get_action, methods = ['POST', 'GET', 'OPTIONS'])
    self.app.register_blueprint(UE)

而后咱们让Flask应用实例注册这个蓝图,这样当咱们服务器启动时,就可使用这个蓝图url地址了。

总结

最后,咱们总结下这个插件的使用方法,咱们新建1个app模块,其源码相似以下:

from flask import Flask, render_template
from ueditor import UEditor

app = Flask(__name__)
ue = UEditor(app)

@app.route('/')
def index():
    return render_template('index.html')

在这里,咱们引入咱们以前编写的插件模块,而后将其实例化操做。而在index.html文件中则为咱们以前引入百度编辑器的内容。
在这里index.html的内容相似以下:

<script type="text/javascript" charset="utf-8" src="/static/ueditor/ueditor.config.js"></script>
<script type="text/javascript" charset="utf-8" src="/static/ueditor/ueditor.all.min.js"> </script>
<script type="text/javascript" charset="utf-8" src="/static/ueditor/lang/zh-cn/zh-cn.js"></script>

<div>
    <div id="editor" style="height:400px;"></div>
    <button id="submit">提交</button>
</div>
<script type="text/javascript">
    var ue = UE.getEditor('editor', {
        serverUrl: "/ueditor/upload/"
    });
</script>

这样咱们便完成了百度编辑器的1个插件的编写了。

参考文章:

http://fex-team.github.io/ueditor/#server-deploy
http://fex-team.github.io/ueditor/#server-config
http://fex-team.github.io/ueditor/#dev-request_specification

相关文章
相关标签/搜索