Django富文本编辑器之tinymce使用

前言

这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题

于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。

微信小程序搜索:Python面试宝典

或可关注原创个人博客:https://lienze.tech

也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习

Tinymce

在某些富文本编辑器中,我们可以支持文件与图片的同时编写,将文字与图片混合排列

django中可以使用TimyMce富文本编辑器进行图文混排功能的实现

下载地址:https://gitee.com/eastside/package/raw/master/tinymce.zip

TinyMce是啥

TinyMCE:是一个轻量级的基于浏览器的所见即所得编辑器,支持目前流行的各种浏览器,由JavaScript写成

功能配置灵活简单,两行代码就可以将编辑器嵌入网页中,并且支持AJAX,加载速度非常快

最重要的是,TinyMCE是一个根据LGPL license发布的自由软件,你可以把它用于商业应用。下图是此编辑器的界面

上传路径

首先配置整个项目的上传文件路径,为了区别与自身的static静态目录

这里的上传文件我们将另外保存至upload文件夹

#settings.py
UPLOAD_ROOT = os.path.join(BASE_DIR,'upload')

模板页面配置

首先需要在使用到tinymce富文本编辑器的html页面下导入必备js文件

<script src="{% static 'js/jquery-1.10.2.min.js' %}" ></script>
<script src="{% static 'js/tinymce_setup.js' %}"></script>

<script src="{% static 'tinymce/js/tinymce/tinymce.min.js' %}"></script>

接下来,在模板页面中加入一个idcontent的输入表单,这里我们以一个文章数据为例

  • 首先是模型层文件定义
#models.py 
class Article(models.Model):
    title = models.CharField(max_length=100,verbose_name='标题')
    author = models.CharField(max_length=100,verbose_name='作者')
    content = models.TextField(verbose_name='内容')

这里的content内容要用到富文本编辑器

  • 接着是模板页面的主要部分
<form method="POST" action='/' enctype="multipart/form-data">
    {% csrf_token %}
    <input type="text" placeholder="文章标题">
    <br>
    <input type="text" placeholder="文章作者">
    <br>
    <input id="rich_content" name="content" value=" ">
    <br>
    <button type="submit">提交</button>
</form>

修改tinymce配置

这里搭配了一个tinymce_setup.js文件,用来控制富文本编辑器所使用的插件等

  • 全文配置如下
tinymce.init({
    // 选择id为content的标签作为编辑器
    selector: '#rich_content',
    // 方向从左到右
    directionality:'ltr',
    // 语言选择中文
    language:'zh_CN',
    // 高度为400 宽度为一半
    height:300,
    width: '50%',
    // 工具栏上面的补丁按钮
    plugins: [
            'advlist autolink link image lists charmap print preview hr anchor pagebreak spellchecker',
            'searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking',
            'save table contextmenu directionality template paste textcolor',
            'codesample imageupload',
    ],
    // 工具栏的补丁按钮
     toolbar: 'insertfile undo redo | \
     styleselect | \
     bold italic | \
     alignleft aligncenter alignright alignjustify | \
     bullist numlist outdent indent | \
     link image | \
     print preview media fullpage | \
     forecolor backcolor emoticons |\
     codesample fontsizeselect fullscreen |\
     imageupload',
    // 字体大小
    fontsize_formats: '10pt 12pt 14pt 18pt 24pt 36pt',
    // 按tab不换行
    nonbreaking_force_tab: true,
    imageupload_url: "/upload_img/",
    // 上传后图片保存为绝对路径
    relative_urls : false,
});
  • 注意:要注意的是imageupload_url配置用来确定当前图片上传所对应的视图路由

图片上传视图

接下来编写富文本编辑器的上传图片路由函数及对应的路由配置

路由映射tinymce_setup.js与中的imageupload_url配置路由相同

这里还要注意,由于此时tinymce的上传图片表单并不是和本身所容纳的form表单一起上传,所以并不会具备csrf_token值,需要我们将上传图片的函数额外进行装饰器装饰,取消csrf_token验证

#views.py
from django.views.decorators.csrf import csrf_exempt
def md5(str_):
    import time
    m = hashlib.md5()
    m.update(str(time.time()).encode())
    filename = m.hexdigest()
    return filename + '.' + str_.split('.')[-1]

@csrf_exempt
def upload_img(request):
    if request.method == 'POST':
        img = request.FILES.get('file')
        if img:
            with open(os.path.join(UPLOAD_ROOT,img.name), 'wb') as fp:
                for buf in img.chunks():
                    fp.write(buf)
                # 迭代读取文件并写入到本地
        response = {}
        response['path'] = '/upload/' + file_name_md5
        response['error'] = False
        return HttpResponse(json.dumps(response))

视图函数还是老样子去接收上传文件并保存即可

  • 路由配置
#urls.py
path('upload_img/',views.upload_img),

文本接收视图

以上的视图函数只能处理上传图片的内容接收

我们的模板页面中还有作者及标题两样表单内容会被POST提交到后台

并且要主要的是,富文本编辑器里除了图片的内容,还有文字等其他内容,这里也需要我们保存下来

  • 这里还需要一个视图函数去接管处理
def index(request):
    if request.method == 'GET':
        return render(request, 'index.html')
    if request.method == 'POST':
        title = request.POST.get('title')
        author = request.POST.get('author')
        content = request.POST.get('content')
        models.Article.objects.create(
            title = title,
            author = author,
            content = content,
        )
        return redirect('/show/')
  • 表单路由
#urls.py
path('',views.index),
  • 这里上传之后,保存在后台的content数据是这个样子
<p><img src="/upload/ec8f8c9a56ed32464a6727741fd58d8d.png" /></p><p>今天<em>一切</em>都是<strong>美丽</strong>的,哈哈哈</p>

上传图片静态映射

当有了上传图片的视图函数及所有内容的接收视图函数

这里还有一个特殊的问题,现在如果在富文本编辑器中选择上传图片,你会发现图片已经在选择时就已经存储到了后台upload文件夹下,这也是为什么我们的图片上传视图函数要单独编写,并且还需要取消csrf_token的验证的原因

除了这个问题你还会发现,在富文本编辑器中,上传的图片是看不到的,是一个坏掉的图片;

使用F12开发者工具你可以看到,这里的图片展示为一个img标签,而标签的src属性内容正是通过上传视图函数返回的response中的path

想让这个path值在访问时,能获取到实际的图片效果,需要我们在路由文件中继续配置,配置专门的upload/xxxx.jpg的图片路由访问,让图片真正展示出来

#urls.py
from django.views.static import serve
re_path('^upload/(?P<path>.*)/$',serve,{'document_root':UPLOAD_ROOT}),

上传后图片的访问路径是/upload/,那么这里的路由也是upload/,之后通过静态文件映射函数serve查找upload文件夹下的同路径同名图片资源

当有了这条路由配置之后,再次再富文本编辑器中加入图片,你就会发现图片出现啦

上传并展示

最后,测试上传图片及文字;并且上传成功之后,重定向到show视图函数

  • 这个视图函数用来提取当前最新的上传数据并返回到模板页面
#views.py
def show(request):
    if request.method == 'GET':
        article = models.Article.objects.all().last()
        return render(request,'show.html',locals())
  • 展示的模板页面
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>展示文章</title>
</head>
<body>
    {% if article %}
        <h3>{{ article.title }}</h3>
        <h4>{{ article.author }}</h4>
        <div>{{ article.content|safe }}</div>
    {% endif %}
</body>
</html>

其实本身富文本编辑器上传的文本内容就已经在一个p标签中,所以这里没有用段落标签

另外由于保存在数据库的文本为html格式,而后台传递来的模板变量django出于安全考虑会自动进行转义,直接观看到的效果不会html样式,只是一些普通字符串;

这里可以使用safe过滤器将内容认定为安全,展示为原始的html效果,其实还不错

总结

富文本编辑器其实就是将用户输入的内容变为html代码

这里的图文混排,只是在图片加入时,单独将图片上传保存,并且回调获取到上传的路径

之后只需要服务端后台配置好相关的上传图片访问路由配置即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李恩泽的技术博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值