如何在Flask Admin的编辑器文本区域上传图片?寻求更简易方案
如何在Flask Admin的富文本编辑器中实现简易图片上传
嘿,我来给你一个比flask-ckeditor更轻量的方案——完全不需要额外安装Python扩展,只用Flask原生功能+一个轻量的富文本编辑器(比如Summernote,直接用CDN引入就行)就能搞定。
第一步:先搞定Flask的文件上传基础配置
首先在你的Flask app里加上上传相关的配置和一个简单的上传接口:
from flask import Flask, request, jsonify, url_for from flask_admin import Admin from flask_admin.contrib.sqla import ModelView import os from werkzeug.utils import secure_filename from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SECRET_KEY'] = '换成你的密钥' # 配置图片上传的文件夹,会自动创建这个目录 app.config['UPLOAD_FOLDER'] = os.path.join(app.root_path, 'static/uploads') # 允许上传的图片格式 ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'} # 可选:设置最大上传文件大小,比如16MB app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 自动创建上传目录 os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) db = SQLAlchemy(app) # 检查文件格式是否合法的小工具函数 def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS # 处理图片上传的接口 @app.route('/upload-image', methods=['POST']) def upload_image(): if 'file' not in request.files: return jsonify({'error': '没找到上传的文件'}), 400 file = request.files['file'] if file.filename == '': return jsonify({'error': '请选择要上传的图片'}), 400 if file and allowed_file(file.filename): # 用secure_filename处理文件名避免安全问题,可加UUID防止重名 filename = secure_filename(file.filename) # 怕重名就加个UUID: # import uuid # filename = f"{uuid.uuid4().hex}_{filename}" file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save(file_path) # 返回图片的可访问URL,供编辑器插入 img_url = url_for('static', filename=f'uploads/{filename}', _external=True) return jsonify({'url': img_url}) return jsonify({'error': '不支持的图片格式'}), 400
第二步:给Flask Admin自定义富文本编辑器字段
假设你有一个需要富文本内容的模型,比如Post:
class Post(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(200), nullable=False) content = db.Column(db.Text) # 这个字段要改成富文本编辑器
接下来我们要自定义一个富文本字段,把Summernote编辑器集成进去,替换掉默认的文本框:
from flask_admin.form import TextAreaField from wtforms.widgets import HTMLString, TextArea # 自定义编辑器的渲染组件 class RichTextWidget(TextArea): def __call__(self, field, **kwargs): # 先渲染默认的文本框,再加上Summernote的初始化代码 base_html = super().__call__(field, **kwargs) return HTMLString(f""" {base_html} <!-- 引入Summernote的CDN资源,不用下载到本地 --> <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.20/dist/summernote-bs4.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/summernote@0.8.20/dist/summernote-bs4.min.js"></script> <script> $(document).ready(function() {{ // 初始化Summernote编辑器 $('#{field.id}').summernote({{ height: 350, // 设置编辑器高度 callbacks: {{ // 监听图片上传事件 onImageUpload: function(files) {{ var formData = new FormData(); formData.append('file', files[0]); // 调用我们刚才写的上传接口 $.ajax({{ url: '/upload-image', method: 'POST', data: formData, contentType: false, processData: false, success: function(res) {{ // 上传成功后把图片插入到编辑器里 $('#{field.id}').summernote('insertImage', res.url); }}, error: function(xhr) {{ alert('图片上传失败:' + xhr.responseJSON.error); }} }}); }} }} }}); }}); </script> """) # 自定义富文本字段 class RichTextAreaField(TextAreaField): widget = RichTextWidget() # 自定义ModelView,把content字段换成我们的富文本字段 class PostAdminView(ModelView): form_overrides = { 'content': RichTextAreaField } # 注册Admin和视图 admin = Admin(app, name='后台管理', template_mode='bootstrap4') admin.add_view(PostAdminView(Post, db.session)) if __name__ == '__main__': with app.app_context(): db.create_all() # 创建数据库表 app.run(debug=True)
第三步:测试功能
启动你的Flask应用,访问Admin页面(默认是/admin),创建或编辑Post的时候,就能看到带图片上传按钮的富文本编辑器了。点击图片按钮选择本地图片,上传成功后会自动插入到编辑器里,完美!
为啥这个方案更简易?
- 不用安装额外的Python包,减少项目依赖。
- 编辑器用CDN引入,不用折腾本地静态文件配置。
- 上传逻辑是Flask原生实现的,代码简单,你想改啥都很方便(比如加图片压缩、改存储路径)。
一些生产环境的小提醒
- 别用本地存储!生产环境建议把图片传到云存储(比如阿里云OSS、AWS S3),避免服务器存储满了。
- 可以给上传接口加个权限验证,比如只有Admin用户能访问,防止恶意上传。
- 要是不喜欢Summernote,换成TinyMCE或者其他轻量编辑器也可以,只要改一下初始化的JS代码就行。
内容的提问来源于stack exchange,提问作者Sadme Rame
相关产品推荐
相关产品推荐

