Django搭建个人博客:使用django-ckeditor富文本编辑器

前面我们已经实现了用Markdown语法写文章了。但是文章的评论用Markdown就不太合适了,你不能强求用户也花时间去熟悉语法啊。另外评论中通常还有表情、带颜色的字体等功能,这些也是Markdown不具备的。

因此富文本编辑器Django-ckeditor就派上用场了。

在后台使用Ckeditor

虚拟环境中安装django-ckeditor:

(env) > pip install django-ckeditor

安装成功后还是老规矩,在settings.py中注册app:

my_blog/settings.py

...
INSTALLED_APPS = [
    ...
    
    'ckeditor',

    ...
]
...

接下来需要修改模型了。用django-ckeditor库自己的富文本字段RichTextField替换普通的文本字段TextField

comment/models.py

...
# django-ckeditor
from ckeditor.fields import RichTextField

class Comment(models.Model):
    ...
    # 之前为 body = models.TextField()
    body = RichTextField()
    ...

记得每次修改模型后要迁移数据

(env) > python manage.py makemigrations
(env) > python manage.py migrate

为方便测试,修改comment/admin.py文件,将评论模块注册到后台中:

comment/admin.py

from django.contrib import admin
from .models import Comment

admin.site.register(Comment)

启动服务器,进入后台的评论页面,发现已经可以使用django-ckeditor了:

功能相当齐全,字体、字号、颜色、链接、表情应有尽有。

如果我只需要部分功能怎么办呢?比如插入flash动画基本就用不到。另外似乎也没看到插入代码块的功能。

ckeditor允许你在settings.py中进行自定义配置:

my_blog/settings.py

...
CKEDITOR_CONFIGS = {
    # django-ckeditor默认使用default配置
    'default': {
        # 编辑器宽度自适应
        'width':'auto',
        'height':'250px',
        # tab键转换空格数
        'tabSpaces': 4,
        # 工具栏风格
        'toolbar': 'Custom',
        # 工具栏按钮
        'toolbar_Custom': [
            # 表情 代码块
            ['Smiley', 'CodeSnippet'], 
            # 字体风格
            ['Bold', 'Italic', 'Underline', 'RemoveFormat', 'Blockquote'],
            # 字体颜色
            ['TextColor', 'BGColor'],
            # 链接
            ['Link', 'Unlink'],
            # 列表
            ['NumberedList', 'BulletedList'],
            # 最大化
            ['Maximize']
        ],
        # 加入代码块插件
        'extraPlugins': ','.join(['codesnippet']),
    }
}

toolbar_Custom中定义需要使用的功能模块;没列出的功能就不再显示了。代码块功能是编辑器自带的插件,需要在extraPlugins中指定使用。效果如下:

编辑富文本搞定后,还需要在前台界面中展示出来。富文本是以类似html的格式进行保存的,因此还要在展示评论的代码加入|safe过滤器,防止浏览器进行转义。

修改detail.html中展示评论的部分代码:

templates/article/detail.html

...

<!-- 显示评论 -->
<h4>共有{{ comments.count }}条评论</h4>
<div>
    {% for comment in comments %}
        ...
        <!-- 修改这里 -->
        <div>{{ comment.body|safe }}</div>
    {% endfor %}
</div>

...

进入文章详情页面看看效果:

代码高亮

代码高亮需要添加额外的插件Prism。在Prism插件官方页面下载(也可以点击这里直接下载)后,将解压出来的prism放到env\Lib\site-packages\ckeditor\static\ckeditor\ckeditor\plugins目录下。注意env是你创建的虚拟环境的目录。

之前你安装的所有库都在这个env目录中的。

然后在Prism官网选择主题:

  • 根据喜好选择一个喜欢的主题
  • 然后选择需要高亮的语言。不清楚就可以全选
  • 勾选行号插件
  • 最后点击DOWNLOAD CSS下载样式

static目录中新建prism目录,将下载好的CSS文件放进去。

注意这里的static是项目中的静态文件目录(与前面的章节相同),而不是env文件夹中的static目录。

然后在需要代码高亮的模板文件中引用prism的静态文件,对代码进行渲染:

templates/article/detail.html

...

<script src="{% static 'ckeditor/ckeditor/plugins/prism/lib/prism/prism_patched.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'prism/prism.css' %}">

...

Prismwidgetlineutils插件添加到配置文件中。后面两个编辑器自带,不用单独下载,添上就可以了:

my_blog/settings.py

...
CKEDITOR_CONFIGS = {
    'default': {
        ...
        # 添加 Prism 相关插件
        'extraPlugins': ','.join(['codesnippet', 'prism', 'widget', 'lineutils']),
    }
}

这样就完成了:

代码高亮效果不错!

在前台使用Ckeditor

为了让用户在前台也能使用富文本编辑器,还得对代码稍加改动。

首先需要把评论的表单传递到文章详情页面中。因此修改article_detail视图:

article/views.py

...
# 引入评论表单
from comment.forms import CommentForm

...
# 文章详情
def article_detail(request, id):
    ...
    
    # 引入评论表单
    comment_form = CommentForm()
    context = { 
        ...
        'comment_form': comment_form,
    }
    ...

然后将detail.html原来评论表单中的正文部分(即前面章节写的<textarea>)替换如下:

templates/article/detail.html

...

<!-- 发表评论 -->
<form ...>
{% csrf_token %}
    <div class="form-group">
        <label for="body">...</label>
        
        <!-- 将之前的<textarea>替换掉 -->
        <!-- <textarea type="text" 
                       class="form-control" 
                       id="body" 
                       name="body" 
                       rows="2"></textarea>  -->
        <div>
            {{ comment_form.media }}
            {{ comment_form.body }}
        </div>
        
    </div>
    <!-- 提交按钮 -->
    ...                   
</form>

...

其中的comment_form.media是编辑器自身的渲染代码,comment_form.body则是评论正文字段。

看看效果:

img

不错,编辑器已经可以正常使用了,但还有一个小问题:似乎编辑器宽度没有自适应,右边大片白白的空间也太浪费了。继续努力。

宽度自适应

首先在配置文件中将宽度设置为auto,这一步我们已经做好了。

Ckeditor编辑器本身有一个inline-block的样式,阻碍了自适应效果,需要用Jquery语法将其清除掉。在详情页面底部加入代码:

templates/article/detail.html

<!-- 注意这是错误的示范! -->

...
<!-- 新增代码 -->
<script>
    $(".django-ckeditor-widget").removeAttr('style');
</script>

<!-- 这个已经有了 -->
{% endblock content %}

$符号代表Jquery语句。这句的意思是:找到页面中class='django-ckeditor-widget'的容器,然后删除这个容器的style属性。

看似没什么问题,然而Bug藏在细节中。注意这是个Jquery语句,那么就要求运行之前先载入Jquery.js。然而在渲染页面时,包含$语句的{% block content %}会插入到base.html模板的Jquery.js标签的前面,导致语句不会生效,并且控制台会报出$ is not defined的错误。

比较容易想到的办法是将引入Jquery.js的标签提到更顶部的位置,在block模板插入前就加载。这样做的问题是JS文件加载通常较慢,它会阻塞后面的代码,从而减缓页面整体加载速度。本文不采用这种办法。

解决方案是在base.html中新增专门用于拼接JavaScript脚本的位置,命名为{% block script %}。注意它必须放置在Jquery标签的后面:

templates/base.html

...

<body>
    ...
    <!-- 已有代码 -->
    <script src="{% static 'jquery/jquery-3.3.1.js' %}"></script>
    ...
    <!-- 新增代码 -->
    {% block script %}{% endblock script %}
</body>

然后将detail.html中的JS代码放到这个块中:

templates/article/detail.html

...

{% block script %}
<script>
    $(".django-ckeditor-widget").removeAttr('style');
</script>
{% endblock script %}

这种方法可以灵活的定义JS脚本的运行顺序,并且代码看起来更加整洁。推荐所有的JS代码都采取这种方法插入。

刷新页面,编辑器就能够宽度自适应了:

发表含有代码块的评论,详情页面的显示如下:

总结

现在,博文和其评论都可以漂亮的排版了。对于有些不喜欢Markdown的人来说,甚至可以连博文都使用django-cdeditor提供的富文本编辑器。我自己还是倾向用Markdown写文章:写作效率比好看更重要,并且主流网站几乎都支持Markdown,多平台发稿很方便。

感谢Aaron Zhao 的个人博客提供了本文的参考。博主还讲解了django-ckeditor上传图片的设置,有兴趣可以前往了解。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269