近期项目开发中,隔壁那个搞python的哥们竟然笑着对我说,希望我能给他写1个百度编辑器的demo,方便他直接调用。
当时真的受宠若惊,这哥们实力不在我之下,只能答应它了。上网搜索下,有1篇文章Flask项目集成富文本编辑器UEditor实现图片上传功能已经有1个现成的例子了。
这篇文章的作者,直接在视图中定义对应的操作,进行一系列图片上传功能的。但是,这并没有满足我的要求,我想要的想过是直接导入一个模块,然后它帮我做完一切的事情。比如这样的形式:
1234 | from xxx import yyy app = Flask(__name__)yyy(app) |
于是只好从头开始学习。
这里,我按照如下的方式从头编写1个Flask版本的百度编辑器的插件:
下面我们开始我们编写插件的过程。
在百度文档中,已经说明UEditor提供4种后台语言,分别为php,asp,asp.net和jsp。首先需要配置serverUrl参数,当ueditor初始化会向serverUrl中的URL发起对后端配置的请求。
而配置的优先级如下:
12 | 后端获取的配置项 > 实例化传入的配置项 > ueditor.config.js文件的配置项 |
可以看到,后端获取的配置项优先级是最高的。在对后端配置请求的过程中,会对配置文件config.json
中的设置进行读取。
而在请求的过程中,百度文档统一请求格式说明中已经说明,通过GET请求上的action参数来判断是什么类型的请求。后端根据不同的请求,进行对应的处理后,需要返回给定格式的内容给前端Javascript。返回的结果一般为JSON的形式。
现在我们已经对百度编辑器UEditor的文档进行了初步的解读,下面我们开始编写我们实际的代码。
在这里,我们主要会用到config和uploadimage这2个配置,其他功能留给读者自己去实现。
在编写代码之前,我打算这样来实现这个插件:
然后我们逐一进行讲解。
这里,我打算将百度默认提供的配置写入到1个config的模块中,本来打算使用类似如下的方式:
123 | imageAction = \”uploadimage\”imageFieldName = \”upfile\”... |
由于时间比较紧,一时半会做不到Flask中读取配置文件后为1个字典的形式,因此简化为该模块直接返回1个字典,如下所示:
12345678910 | 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的类用于处理这个操作:
12 | class UEditor(object): pass |
首先我们要做的第一步是解决请求参数的问题,让不同的请求调用不同的处理函数,我们将其定义在该类的get_action
函数中:
1234 | def get_action(self): action = request.args.get(\’action\’) if action: return self.handle(action) |
我们将具体处理的过程放在handle函数中,在这个函数中,我们要做2件事情:
然后是handle函数其具体的源码:
1234567891011 | 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时我们应该将配置文件中的内容直接返回即可:
12 | def get_config(): return CONFIG |
而在上传图片的时候,我们根据配置文件中的配置,将其传递给上传文件的模块,这里我们直接把之前Flask那篇文章作者git上的Uploader拿了过来。其实他也是参考php的实现的源码,将其修改为python版本而言。
1234567891011121314 | 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地址即可操作了。一般我们的代码是这样的:
12345678910111213 | <div> <div id=\”editor\” style=\”height:400px;\”></div></div> |
之前我们后端代码的过程只解决了图片上传的问题,关于serverUrl关联到对应URL的问题还一直没有解决。
为了解决这个问题,我打算引入蓝图和Flask提供的add_url_rule
来解决这个问题。
12345678910 | 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模块,其源码类似如下:
123456789 | from flask import Flask, render_templatefrom ueditor import UEditor app = Flask(__name__)ue = UEditor(app) @app.route(\’/\’)def index(): return render_template(\’index.html\’) |
在这里,我们引入我们之前编写的插件模块,然后将其实例化操作。而在index.html文件中则为我们之前引入百度编辑器的内容。
在这里index.html
的内容类似如下:
12345678910111213 | <div> <div id=\”editor\” style=\”height:400px;\”></div> <button id=\”submit\”>提交</button></div> |
这样我们便完成了百度编辑器的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
下一篇:机器学习从入门到放弃之KNN算法