【八】添加文章功能实现

【一】添加文章功能实现

【引言】

  • 在添加文章的过程中遇到很多问题

【路由】

  • 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攻击

    • 解决办法

      • 引入第三方模块

      • 通过实例化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攻击的解决办法:

  • 输入过滤和验证:对用户输入的内容进行严格的过滤和验证,防止恶意脚本的注入。例如,对特殊字符进行转义、限制输入长度等。
  • 输出编码:在将数据输出到网页时,对特殊字符进行编码,确保浏览器将其作为纯文本展示而非解释执行。
  • 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】首先下载富文本编辑器

  • 将压缩包下载到本地

  • 查看编辑器使用文档

http://kindeditor.net/docs/usage.html

【2】修改HTML页面

  • 在需要显示编辑器的位置添加textarea输入框。
<textarea id="editor_id" name="content" style="width:700px;height:300px;">
&lt;strong&gt;HTML内容&lt;/strong&gt;
</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 }}'
    },
});
posted @ 2023-07-21 15:50  Chimengmeng  阅读(37)  评论(0编辑  收藏  举报
/* */