【八】添加文章功能实现
【一】添加文章功能实现
【引言】
- 在添加文章的过程中遇到很多问题
【路由】
add/article/
【二】添加文章内容页面搭建
【1】新建文件夹存储相关页面
- base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 本地 链接 引入方法 -->
<!-- Websource 文件夹 拷贝到当前文件夹下即可使用 -->
<!-- jQuery 文件(先导入) -->
<script src="{% static 'js/jquery.min.js' %}"></script>
<!-- Bootstrap 的 JS 文件 (动画效果需要jQuery) -->
<script src="{% static 'plugins/Bootstrap/js/bootstrap.min.js' %}"></script>
<!-- Bootstrap 的 CSS 样式文件 -->
<link rel="stylesheet" href="{% static 'plugins/Bootstrap/css/bootstrap.min.css' %}">
<!-- bootstrap-sweetalert(弹框) 的 CSS 文件 -->
<link rel="stylesheet" href="{% static 'plugins/bootstrap-sweetalert/dist/sweetalert.css' %}">
<!-- bootstrap-sweetalert(弹框) 的 JS 文件 -->
<script src="{% static 'plugins/bootstrap-sweetalert/dist/sweetalert.js' %}"></script>
<!-- 以下为 css样式书写区 -->
<link rel="stylesheet" href="/Source/css/{{ blog.site_theme }}">
<style>
{% block css %}
{% endblock %}
</style>
</head>
<body>
{#导航条#}
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/home/">{{ request.user.blog.site_title }}</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">BBS <span class="sr-only">(current)</span></a></li>
<li><a href="#">链接</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">更多 <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">提交</button>
</form>
<ul class="nav navbar-nav navbar-right">
{% if request.user.is_authenticated %}
<li><a href="/backend/">{{ request.user.username }}</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">更多操作 <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#" data-toggle="modal" data-target=".bs-example-modal-lg">修改密码</a></li>
<li><a href="#">修改头像</a></li>
<li><a href="#">后台管理</a></li>
<li role="separator" class="divider"></li>
<li><a href="/log_out/">退出登录</a></li>
</ul>
<!-- Large modal 修改密码模态框 -->
<!-- Large modal -->
<div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog"
aria-labelledby="myLargeModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<h1 class="text-center">修改密码</h1>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<label for="">用户名</label>
<input type="text" disabled value="{{ request.user.username }}"
class="form-control">
</div>
<div class="form-group">
<label for="">原密码</label>
<input type="password" id="id_old_password" class="form-control">
</div>
<div class="form-group">
<label for="">新密码</label>
<input type="password" id="id_new_password" class="form-control">
</div>
<div class="form-group">
<label for="">确认密码</label>
<input type="password" id="id_confirm_password" class="form-control">
</div>
<button type="button" class="btn btn-default pull-right"
data-dismiss="modal">
取消修改
</button>
<button class="btn btn-danger center-block pull-right"
style="margin-bottom: 30px;margin-right: 10px" id="id_edit">
确认修改
</button>
<span style="color: red" id="id_pwd_error"></span>
</div>
</div>
</div>
</div>
</div>
</li>
{% else %}
<li><a href="/register/">注册</a></li>
<li><a href="/login/">登陆</a></li>
{% endif %}
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{#导航条内部#}
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne"
aria-expanded="true" aria-controls="collapseOne">
操作
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
aria-labelledby="headingOne">
<div class="panel-body">
<a href="/add/article/">添加文章</a>
</div>
</div>
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
aria-labelledby="headingOne">
<div class="panel-body">
<a href="">添加随笔</a>
</div>
</div>
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
aria-labelledby="headingOne">
<div class="panel-body">
<a href="">草稿箱</a>
</div>
</div>
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
aria-labelledby="headingOne">
<div class="panel-body">
<a href="">其他</a>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-9">
{% block content %}
<div>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#home" aria-controls="home" role="tab"
data-toggle="tab">文章</a></li>
<li role="presentation"><a href="#profile" aria-controls="profile" role="tab"
data-toggle="tab">随笔</a>
</li>
<li role="presentation"><a href="#messages" aria-controls="messages" role="tab"
data-toggle="tab">草稿</a></li>
<li role="presentation"><a href="#files" aria-controls="messages" role="tab"
data-toggle="tab">文件</a></li>
<li role="presentation"><a href="#settings" aria-controls="settings" role="tab"
data-toggle="tab">设置</a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="home">
{% block article %}
文章页面
{% endblock %}
</div>
<div role="tabpanel" class="tab-pane" id="profile">随笔页面</div>
<div role="tabpanel" class="tab-pane" id="messages">草稿页面</div>
<div role="tabpanel" class="tab-pane" id="files">文件页面</div>
<div role="tabpanel" class="tab-pane" id="settings">设置页面</div>
</div>
</div>
{% endblock %}
</div>
</div>
</div>
{% block js %}
{% endblock %}
</body>
</html>
- 基础页面搭建
- 页面排版采用3/9分布
- 左侧展示操作的相关选项
- 右侧展示文章列表及相关功能
- 外边框导航栏采用首页的外部导航栏
【2】添加文章页面搭建
{% extends 'backend/base.html' %}
{% load static %}
{% block article %}
<h3>添加文章</h3>
{# form表单提交数据 #}
<form action="" method="post">
{% csrf_token %}
<p>标题</p>
<div>
<input type="text" name="title" class="form-control">
</div>
<p>内容</p>
<div>
<textarea name="content" id="id_content" cols="30" rows="10">
</textarea>
</div>
<p>分类</p>
<div>
{% for category in category_list %}
<input type="radio" value="{{ category.pk }}" name="category">{{ category.name }}
{% endfor %}
<p>标签</p>
{% for tag in tag_list %}
<input type="checkbox" value="{{ tag.pk }}" name="tag">{{ tag.name }}
{% endfor %}
</div>
<input type="submit" class="btn btn-danger">
</form>
{% endblock %}
{% block js %}
<script charset="utf-8" src="{% static 'js/kindeditor/kindeditor-all-min.js' %}"></script>
<script>
var callBackPath = '{% static 'js/kindeditor/redirect.html' %}'
KindEditor.ready(function (K) {
window.editor = K.create('#id_content', {
width: '100 %',
height: '300px',
// 控制上面的功能的多少
items: [
'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste',
'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright',
'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/',
'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold',
'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image', 'multiimage',
'flash', 'media', 'insertfile', 'table', 'hr', 'emoticons', 'baidumap', 'pagebreak',
'anchor', 'link', 'unlink', '|', 'about'
],
resizeType: 1,
allowImageUpload: true,//允许上传图片
allowFileManager: true, //允许对上传图片进行管理
// 上传图片的后端存储路径
uploadJson: '/upload_img/?callBackPath=' + callBackPath, // 后端提交路径
afterUpload: function () {
this.sync();
}, //图片上传后,将上传内容同步到textarea中
afterBlur: function () {
this.sync();
}, //失去焦点时,将上传内容同步到textarea中
afterCreate: function () {
this.sync();
},
extraFileUploadParams: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
});
});
</script>
{% endblock %}
- 使用富文本编辑器 KindEditor 记录输入的文本内容
- 利用form表单向后端提交数据
【三】添加文章后端逻辑实现
【1】添加文章主接口
# 添加文章接口
@login_required
def add_article(request):
if request.method == "POST":
# 获取用户文章的标题
title = request.POST.get('title')
content = request.POST.get('content')
category_id = request.POST.get('category')
tag_list = request.POST.getlist('tag')
# BS4
soup = BeautifulSoup(content, 'lxml')
tags = soup.find_all()
# 获取所有的标签
for tag in tags:
# 获取页面所有的标签
tag_name = tag.name
# 筛选出针对 script 的标签 直接删除
print(tag_name)
if tag_name == "script":
print("已删除script")
tag.decompose()
# 文章简介
# (1)直接切取 content 150个字符
# desc = content[0:150]
desc = soup.text[0:150]
# 存储数据
article_obj = models.Article.objects.create(
title=title,
content=str(soup),
desc=desc,
category_id=category_id,
blog=request.user.blog
)
# 文章和标签的关系表,是我们自己创建的,没法使用add set remove clear 方法
# 手动操作关系表 --- 一次性可能需要创建多条数据 ---- 批量插入 bulk_create()
article_obj_list = []
for i in tag_list:
tag_obj = models.ArticleToTag(article=article_obj, tag_id=i)
article_obj_list.append(tag_obj)
# 批量插入数据
models.ArticleToTag.objects.bulk_create(article_obj_list)
# 跳转到狗太管理展示页面
return redirect('/backend/')
# 分类和标签
category_list = models.Category.objects.filter(blog=request.user.blog)
tag_list = models.CategoryTag.objects.filter(blog=request.user.blog)
return render(request, 'backend/add_article.html', locals())
-
主逻辑分析
-
只有登录用户才能进行添加文章
- 进行登陆校验
@login_required
- 进行登陆校验
-
判断当前请求的方式
if request.method == "POST"
-
获取前端传入的数据
- 文章标题
title = request.POST.get('title')
- 文章内容
content = request.POST.get('content')
- 文章对用的分类ID
category_id = request.POST.get('category')
- 文章对应的标签ID
tag_list = request.POST.getlist('tag')
- 文章标题
-
对文本内容进行进一步的处理
-
防止XSS攻击
-
解决办法
-
引入第三方模块
-
beautiful
pip install beautifulsoup4 # bs4解析模块 pip install lxml # 解析器模块
详解:Day 10 10.1 数据解析方法之-BS4 - Chimengmeng - 博客园 (cnblogs.com)
-
-
通过实例化bs4对象,并将标签页面交给bs4处理
soup = BeautifulSoup(content, 'lxml')
-
将文本内容
- 即标签页面交给bs4处理,拿到所有的标签
tags = soup.find_all()
-
遍历每一个标签名
- 当其中 有script标签时,将标签删除
tag.decompose()
-
-
切取文章摘要
- 本部分采用暴力切取
- 不对文章大意进行模拟概括,直接切取文章的前150个字符
desc = soup.text[0:150]
-
调用对象存储数据
# 存储数据 article_obj = models.Article.objects.create( title=title, content=str(soup), desc=desc, category_id=category_id, blog=request.user.blog )
-
-
数据很多所以才用批量插入方法
bulk_create
# 存储数据 article_obj = models.Article.objects.create( title=title, content=str(soup), desc=desc, category_id=category_id, blog=request.user.blog ) # 文章和标签的关系表,是我们自己创建的,没法使用add set remove clear 方法 # 手动操作关系表 --- 一次性可能需要创建多条数据 ---- 批量插入 bulk_create() article_obj_list = [] for i in tag_list: tag_obj = models.ArticleToTag(article=article_obj, tag_id=i) article_obj_list.append(tag_obj) # 批量插入数据 models.ArticleToTag.objects.bulk_create(article_obj_list) # 跳转到狗太管理展示页面 return redirect('/backend/')
- 存储完成自动返回后台管理页面
【2】处理富文本编辑的图片接口
# 富文本编辑器上传文件接口
def upload_img(request):
'''
# 必须返回指定数据格式,否则会报错
:param request:
:return:
//成功时
{
"error" : 0,
"url" : "http://www.example.com/path/to/file.ext"
}
//失败时
{
"error" : 1,
'''
# 定义返回的数据格式
back_dict = {"error": 0}
# 用户写文章上传的图片 也算静态资源 也应该防盗 Source 文件
if request.method == "POST":
# 获取用户上传的图片对象
# print(request.FILES) # 通过打印返回的文件名,知道了文件名
file_obj = request.FILES.get("imgFile")
# 手动拼接存储文件的路径
file_dir = os.path.join(BASE_DIR, 'Source', 'article_img')
# 优化 : 判断当前文件夹是否存在,如果不存在则创建
if not os.path.exists(file_dir):
os.mkdir(file_dir)
# 拼接图片的文件完整路径
file_path = os.path.join(file_dir, file_obj.name)
with open(file_path, 'wb') as f:
for line in file_obj:
f.write(line)
# 不使用 file_path 路径太完全没有接口
back_dict['url'] = f'/Source/article_img/{file_obj.name}'
print('back_dict:>>>', back_dict)
return JsonResponse(back_dict)
-
参照官方文档使用官方文档要求的返回信息的格式
back_dict = {"error": 0}
-
判断当前请求方式
if request.method == "POST"
-
拿到当前传过来的文件对象
file_obj = request.FILES.get("imgFile")
-
拼接文件存储的路径
file_dir = os.path.join(BASE_DIR, 'Source', 'article_img')
-
做一步优化判断,文件夹不存在时自动创建文件
if not os.path.exists(file_dir):os.mkdir(file_dir)
-
拼接图片的完成路径
file_path = os.path.join(file_dir, file_obj.name)
-
打开文件路径进行文件的存储
-
存储完成返回指定数据格式
- 返回当前图片给前端页面展示
【补充】XSS攻击
【一】XSS攻击介绍
- XSS(跨站脚本攻击)是一种常见的网络安全漏洞
- 攻击者通过在网页中注入恶意脚本来实现攻击。
- 当用户访问受到攻击的网页时
- 恶意脚本将在用户的浏览器中执行
- 从而导致各种安全问题
- 包括会话劫持、敏感信息泄露等。
【二】XSS攻击的原理:
- XSS攻击利用了网页对用户输入的信任
- 攻击者可以将恶意脚本注入到网页中
- 当其他用户访问该页面时
- 恶意脚本将被执行。
- 攻击者可以通过恶意脚本获取用户的敏感信息
- 或者进行其他非法操作。
【三】XSS攻击的分类:
- XSS攻击可分为反射型XSS、存储型XSS和DOM-based XSS三种类型。
- 反射型XSS攻击通过伪装成合法链接诱使用户点击
- 将恶意脚本作为URL参数发送给目标网站
- 并返回给用户执行;
- 存储型XSS攻击将恶意脚本存储在目标网站的数据库中
- 当其他用户访问该网站时
- 恶意脚本被加载并执行;
- DOM-based XSS攻击则是通过修改网页的DOM结构来执行恶意脚本。
- 反射型XSS攻击通过伪装成合法链接诱使用户点击
【四】XSS攻击的演示:
- 以反射型XSS攻击为例
- 假设有一个搜索功能的网站
- 用户可以通过输入关键词进行搜索。
- 攻击者可以构造一个恶意链接
- 其中包含注入恶意脚本的关键词。
- 当用户点击该链接并触发搜索时
- 恶意脚本就会执行
- 可能导致用户信息泄露或其他安全问题。
【五】XSS攻击的解决办法:
- 输入过滤和验证:对用户输入的内容进行严格的过滤和验证,防止恶意脚本的注入。例如,对特殊字符进行转义、限制输入长度等。
- 输出编码:在将数据输出到网页时,对特殊字符进行编码,确保浏览器将其作为纯文本展示而非解释执行。
- CSP(内容安全策略):通过配置CSP,限制网页中可以加载和执行的资源,减少XSS攻击的威胁。
- HTTP-only标记:将敏感的cookie标记为HTTP-only,防止被恶意脚本获取。
【补充】富文本编辑器 KindEditor
【一】介绍
- KindEditor是一个富文本编辑器,旨在为开发人员提供在网页上进行富文本编辑的功能。
- 它基于JavaScript开发,并且具有简单易用、功能丰富的特点,适用于Web应用程序的构建。
【二】特点
- 可配置性:KindEditor通过配置参数让你能够对编辑器进行自定义设置,以满足不同的需求。
- 轻量级:它的核心代码很小,加载速度快,不会给网页带来额外的负担。
- 兼容性良好:KindEditor支持主流的浏览器,包括IE、Firefox、Chrome等。
- 支持多种功能:包括字体、颜色、对齐方式、图片上传、表格插入、链接等编辑功能。
- 扩展性强:允许开发人员根据需求进行插件开发,以扩展编辑器功能。
【三】使用方法
- 下载KindEditor:你可以在KindEditor官网上下载到最新的版本,并将其解压缩到你的项目目录下。
- 引入相关文件:在HTML文件中引入KindEditor所需的CSS和JavaScript文件,确保文件路径正确。
- 创建编辑器实例:通过调用KindEditor.create()方法创建一个富文本编辑器实例,并指定编辑器的ID和配置参数。
- 使用编辑器功能:通过编辑器实例提供的API方法,可以实现对文本的格式设置、插入图片、添加链接等操作。
- 提交表单数据:在提交表单数据时,可以通过调用KindEditor.sync()方法将编辑器的内容同步到textarea元素中,以便后端处理。
【四】开发文档示例详解
- 富文本编辑器可以使我们摆脱光秃秃的文本输入框,让我们支持输入代码图片等内容并自动加载格式
- 富文本编辑器的功能有很多
- 在使用过程中要参照开发文档进行相关的配置才能使用
- 这里我只讲我的KindEditor使用过程
KindEditor 官网:http://kindeditor.net/doc.php
【1】首先下载富文本编辑器
-
将压缩包下载到本地
-
查看编辑器使用文档
【2】修改HTML页面
- 在需要显示编辑器的位置添加textarea输入框。
<textarea id="editor_id" name="content" style="width:700px;height:300px;">
<strong>HTML内容</strong>
</textarea>
-
id在当前页面必须是唯一的值。
-
在textarea里设置HTML内容即可实现编辑,在这里需要注意的是,如果从服务器端程序(ASP、PHP、ASP.NET等)直接显示内容
- 则必须转换HTML特殊字符(>,<,&,”)。
- 具体请参考各语言目录下面的demo.xxx程序
- 目前支持ASP、ASP.NET、PHP、JSP。
-
在有些浏览器上不设宽度和高度可能显示有问题
- 所以最好设一下宽度和高度。
- 宽度和高度可用inline样式设置
- 也可用 编辑器初始化参数 设置。
-
在该HTML页面添加以下脚本。
<script charset="utf-8" src="/editor/kindeditor.js"></script>
<script charset="utf-8" src="/editor/lang/zh-CN.js"></script>
<script>
KindEditor.ready(function(K) {
window.editor = K.create('#editor_id');
});
</script>
- 通过自定义ID值取到我们写好的文本域标签
【3】方法小结
- 先下载文件
- 定义文本域标签并给文本域标签定义属性
- 定义属性是为了方便后面的标签选择时使用
- 在js代码部分引入官方文档的固定写法
- 先引入富文本域文件
- 利用属性选择器找到我们需要使用编辑器的文本域标签
【五】个人案例演示
【1】定义文本域标签及赋予属性
<p>内容</p>
<div>
<textarea name="content" id="id_content" cols="30" rows="10">
</textarea>
</div>
【2】调用富文本编辑器配置
- 引入kindeditor支持js文件
- 利用属性选择到相应的文本域标签
- 配置参数
<script charset="utf-8" src="{% static 'js/kindeditor/kindeditor-all-min.js' %}"></script>
<script>
var callBackPath = '{% static 'js/kindeditor/redirect.html' %}'
KindEditor.ready(function (K) {
window.editor = K.create('#id_content', {
width: '100 %',
height: '300px',
// 控制上面的功能的多少
items: [
'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste',
'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright',
'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/',
'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold',
'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image', 'multiimage',
'flash', 'media', 'insertfile', 'table', 'hr', 'emoticons', 'baidumap', 'pagebreak',
'anchor', 'link', 'unlink', '|', 'about'
],
resizeType: 1,
allowImageUpload: true,//允许上传图片
allowFileManager: true, //允许对上传图片进行管理
// 上传图片的后端存储路径
uploadJson: '/upload_img/?callBackPath=' + callBackPath, // 后端提交路径
afterUpload: function () {
this.sync();
}, //图片上传后,将上传内容同步到textarea中
afterBlur: function () {
this.sync();
}, //失去焦点时,将上传内容同步到textarea中
afterCreate: function () {
this.sync();
},
extraFileUploadParams: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
});
});
</script>
- KindEditor部分参数详解
- 支持用户上传图片配置
K.create('#id_content', {
width: '100 %',
height: '300px',
// 控制上面的功能的多少
items: [
'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste',
'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright',
'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/',
'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold',
'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image', 'multiimage',
'flash', 'media', 'insertfile', 'table', 'hr', 'emoticons', 'baidumap', 'pagebreak',
'anchor', 'link', 'unlink', '|', 'about'
],
resizeType: 1,
allowImageUpload: true,//允许上传图片
allowFileManager: true, //允许对上传图片进行管理
// 上传图片的后端存储路径
uploadJson: '/upload_img/?callBackPath=' + callBackPath, // 后端提交路径
afterUpload: function () {
this.sync();
}, //图片上传后,将上传内容同步到textarea中
afterBlur: function () {
this.sync();
}, //失去焦点时,将上传内容同步到textarea中
afterCreate: function () {
this.sync();
},
extraFileUploadParams: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
});
本文来自博客园,作者:Chimengmeng,转载请注明原文链接:https://www.cnblogs.com/dream-ze/p/17571621.html