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

3279阅读 · 50评论 · 2019/03/21发布   前往评论

前面我们已经实现了用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了:

img

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

如果我只需要部分功能怎么办呢?比如插入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中指定使用。效果如下:

img

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

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

templates/article/detail.html

...

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

...

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

img

代码高亮

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

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

然后在Prism官网选择主题:

img

  • 根据喜好选择一个喜欢的主题
  • 然后选择需要高亮的语言。不清楚就可以全选
  • 勾选行号插件
  • 最后点击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']),
    }
}

这样就完成了:

img

代码高亮效果不错!

在前台使用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代码都采取这种方法插入。

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

img

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

img

总结

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

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




本文作者: 杜赛
发布时间: 2019年03月21日 - 21:15
最后更新: 2019年03月21日 - 21:34
知识共享许可协议   转载请保留原文链接及作者


登录 后回复

共有50条评论

avatar
qq5216 么么哒! 2

def article_delete(request,article_id):
    models.Article.objects.filter(article_id=article_id).delete()
    return HttpResponseRedirect('/blog/ind

删除文章后的id会重新编写   ,导致在网页中会出现文章id不存在的情况怎么办

5个月前 回复


avatar
杜赛 [博主] qq5216 么么哒! 2

没懂你的意思

5个月前 回复


avatar
R 么么哒! 3

博主,您好,我在文章正文使用富文本编辑器是修改功能没有保留原文,能不能请教一下您,怎么处理

4个月前 回复


avatar
杜赛 [博主] R 么么哒! 3

是用的cdeditor吗?

视图中将旧原文传递到表单的initial参数中,像这样:

article_form = ArticleForm(initial=old_content)

然后在模板文件中正常渲染表单,就可以了

4个月前 回复


avatar
mapsh 么么哒! 2

博主你好,我也使用django-cdeditor,但是运行起来总是出现 ckeditor.js:258 Uncaught TypeError: Cannot set property 'dir' of undefined 的错误,然后编辑框都不出现,不知道哪里设置错误。

4个月前 回复


avatar
杜赛 [博主] mapsh 么么哒! 2

我没遇到过这种错误,所以无法准确回答哪里有问题。

不过这个报错很多时候是由于 js 文件路径不对导致的。详情见这里:Specifying the Editor Path

4个月前 回复


avatar
mapsh 杜赛 [博主] 么么哒! 2

博主能把你的setting.py文件贴出来下嘛,一直报这个错误

ckeditor.js:258 Uncaught TypeError: Cannot set property 'dir' of undefined

 

4个月前 回复


avatar
mapsh 杜赛 [博主] 么么哒! 2

我下载了您的代码下来,运行也是报错,不明白到底啥情况了

ckeditor.js:264 Uncaught Error: [CKEDITOR.resourceManager.load] Resource name "codesnippet" was not found at "http://127.0.0.1:8000/static/ckeditor/ckeditor/plugins/codesnippet/plugin.js?t=J39A".
    at CKEDITOR.resourceManager.<anonymous> (ckeditor.js:264)
    at e (ckeditor.js:259)
    at Array.y (ckeditor.js:259)
    at v (ckeditor.js:259)
    at HTMLScriptElement.CKEDITOR.env.ie.e.$.onerror (ckeditor.js:260)

 

4个月前 回复


avatar
杜赛 [博主] mapsh 么么哒! 3

看样子是codesnippet插件没加载上。

你在配置中删除掉这个插件,看看能正常运行不

4个月前 回复


avatar
mapsh 杜赛 [博主] 么么哒! 3

真的是神奇了,我把插件删了,你的程序就可以正常了,但是我拷贝你的设置过来,我的项目一样的问题

4个月前 回复


avatar
mapsh 杜赛 [博主] 么么哒! 2

我发现了, 我setting里是

LANGUAGE_CODE = 'zh-Hans'

改成

LANGUAGE_CODE = 'en-us'

就不报错了,但是我后台需要中文,这要怎么弄呢

4个月前 回复


avatar
杜赛 [博主] mapsh 么么哒! 2

把ckeditor的语言设置为英文试试

4个月前 回复


avatar
mapsh 杜赛 [博主] 么么哒! 3

    def _set_config(self):
        lang = get_language()
        print(lang)
        if lang == 'zh-hans':
            lang = 'zh-cn'
        elif lang == 'zh-hant':
            lang = 'zh'
        self.config['language'] = lang

我找到django-cdeditor里的代码了, 改成小写就可以

LANGUAGE_CODE = 'zh-hans'

在此非常感谢博主这几天的指导yes,博主非常棒

4个月前 回复


avatar
杜赛 [博主] mapsh 么么哒! 4

4个月前 回复


avatar
ychda mapsh 么么哒! 3

zh-hans

 

大小写的问题?

2个月前 回复


avatar
KuKKKK 么么哒! 2

在前台输入的文章,传到后台之后每一行的文字都被加上了标签,这样导致markdown的格式不能显示怎么办

4个月前 回复


avatar
杜赛 [博主] KuKKKK 么么哒! 3

富文本编辑器和Markdown最好不要混着用

4个月前 回复


avatar
Jiangyciauh-Dawn 么么哒! 3
本回复已被 Jiangyciauh-Dawn 删除

3个月前 回复


avatar
pidada 么么哒! 2

博主,还是那个老问题:我添加了django-CKeditor。在后台和前端中都不能显示,就是现在这个评论界面没有,也没有报错,博主,怎么破?

# body = models.TextField()
body = RichTextField()   # 使用富文本无法显示

 

3个月前 回复


avatar
杜赛 [博主] pidada 么么哒! 3

你这样空口问,什么信息也没有,我当然也不知道怎么破啊。。

你先在后台把ckeditor调通,因为后台是最简单的。

重新把安装流程走一遍。

还不行的话把相关代码、图片用Email全部发给我看一下。

3个月前 回复


avatar
ac1864 么么哒! 3

过关,顺便查了一下CKeditor如何上传图片。

收获满满。

3个月前 回复


avatar
杜赛 [博主] ac1864 么么哒! 3

不错啊,快把我教程看完了。你可以毕业了

3个月前 回复


avatar
Austin 么么哒! 4

博主你好,我有两个小问题1.我的评论的富文本编辑器在前台可以引入,但是没法使用上边的几个按钮,2.而且从后端加进去的表情符号就还会带上

<p><img alt="yes" height="23" src="http://127.0.0.1:8000/static/ckeditor/ckeditor/plugins/smiley/images/thumbs_up.png" title="yes" width="23" />(这里是我写的评论)</p> 这个改东西

望博主能帮忙解答,十分感谢

2个月前 回复


avatar
杜赛 [博主] Austin 么么哒! 3

  1. 没法用是什么意思?配置文件写对了吗?修改配置中的某些按钮,有什么效果?前后端有没有报错?
  2. 这个img标签是ckeditor的点赞表情,为什么会出现我就不清楚了。注意各个过程中有没有报错,有的话可以贴出来我看看。

2个月前 回复


avatar
Austin 杜赛 [博主] 么么哒! 3

1.没有出现明显的报错,就是前台出现了富文本编辑器的框,但是上面表情,加粗,这些按钮只可以点但是无法使用,就是看起来似乎只有装饰作用

2、后来又瞎弄了下,不知道为什么又好了。

2个月前 回复


avatar
杜赛 [博主] Austin 么么哒! 4

听描述像是插件没安装好,或者配置没对,新建个项目重新走一遍试试。

浏览器的控制台有报错吗?

2个月前 回复


avatar
littleh 么么哒! 3

你好博主,请问一下:我在前台应用ckeditor时总是显示不出来 评论框 是怎么回事啊?查看源代码也没什么问题

<div><script type="text/javascript" src="/static/ckeditor/ckeditor-init.js" data-ckeditor-basepath="/static/ckeditor/ckeditor/" id="ckeditor-init-script"></script>
<script type="text/javascript" src="/static/ckeditor/ckeditor/ckeditor.js"></script>
<div class="django-ckeditor-widget" data-field-id="id_body" style="display: inline-block;">
<textarea cols="40" id="id_body" name="body" rows="10" required data-processed="0" data-config="{&quot;skin&quot;: &quot;moono-lisa&quot;, &quot;toolbar_Basic&quot;: [[&quot;Source&quot;, &quot;-&quot;, &quot;Bold&quot;, &quot;Italic&quot;]], &quot;toolbar_Full&quot;: [[&quot;Styles&quot;, &quot;Format&quot;, &quot;Bold&quot;, &quot;Italic&quot;, &quot;Underline&quot;, &quot;Strike&quot;, &quot;SpellChecker&quot;, &quot;Undo&quot;, &quot;Redo&quot;], [&quot;Link&quot;, &quot;Unlink&quot;, &quot;Anchor&quot;], [&quot;Image&quot;, &quot;Flash&quot;, &quot;Table&quot;, &quot;HorizontalRule&quot;], [&quot;TextColor&quot;, &quot;BGColor&quot;], [&quot;Smiley&quot;, &quot;SpecialChar&quot;], [&quot;Source&quot;]], &quot;toolbar&quot;: &quot;Custom&quot;, &quot;height&quot;: &quot;250px&quot;, &quot;width&quot;: &quot;auto&quot;, &quot;filebrowserWindowWidth&quot;: 940, &quot;filebrowserWindowHeight&quot;: 725, &quot;tabSpaces&quot;: 4, &quot;toolbar_Custom&quot;: [[&quot;Smiley&quot;, &quot;CodeSnippet&quot;], [&quot;Bold&quot;, &quot;Italic&quot;, &quot;Underline&quot;, &quot;RemoveFormat&quot;, &quot;Blockquote&quot;], [&quot;TextColor&quot;, &quot;BGColor&quot;], [&quot;Link&quot;, &quot;Unlink&quot;], [&quot;NumberedList&quot;, &quot;BulletedList&quot;], [&quot;Maximize&quot;]], &quot;extraPlugins&quot;: &quot;codesnippet,prism,widget,lineutils&quot;, &quot;language&quot;: &quot;zh-Hans&quot;}" data-external-plugin-resources="[]" data-id="id_body" data-type="ckeditortype"></textarea>

这是我的ckeditor默认的代码?谢谢

1个月前 回复


avatar
杜赛 [博主] littleh 么么哒! 3

浏览器控制台有什么报错吗?

1个月前 回复


avatar
littleh 杜赛 [博主] 么么哒! 3
本回复已被 littleh 删除

1个月前 回复


avatar
littleh 杜赛 [博主] 么么哒! 2

好像是显示ckeditor.js找不到,jquery.js也有问题。博主,这是什么问题啊,谢谢

1个月前 回复


avatar
杜赛 [博主] littleh 么么哒! 3

说明你的js文件全都没有正确引入吧。

好好检查一下相关代码,实在不行把有关部分全部截图发我邮箱,我帮你看看

1个月前 回复


avatar
littleh 杜赛 [博主] 么么哒! 3

好的 十分感谢 我再检查一下 

1个月前 回复


avatar
littleh 杜赛 [博主] 么么哒! 2

感谢 问题解决了laugh

1个月前 回复


avatar
sys0613 么么哒! 4

你好博主,看到现在,感觉到知识的匮乏,像那些轮子,您是怎么知道的??有什么学习方法么?

感觉现在面临两个问题,

1、怎么想到用哪个轮子?这个有什么方法么?还是说有固定的网站,专门查各个轮子用的?

2、轮子的具体用法,这个我感觉就得靠轮子的使用说明,或者手册了吧?

28天前 回复


avatar
杜赛 [博主] sys0613 么么哒! 3

我教程里推荐过一个网站,叫 Django Packages,里面搜集了几乎所有好用的轮子。还有就是当你需要某些通用功能时,就Google一下,看看别人都用的什么轮子,根据情况自己选择合适的。

轮子的用法,读官方文档。好轮子一定有好文档,否则你就不要用。

27天前 回复


avatar
zhj 么么哒! 3

博主好,我想问一下,在代码高亮这一块

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

这个static路径是env下的吗,我用的pycharm.然后也是把Prism插件下载解压放到项目的venv对应的plugins文件下,但是代码还是高亮不出来啊

cool

28天前 回复


avatar
杜赛 [博主] zhj 么么哒! 2

这是在项目的static目录,不是虚拟环境中

27天前 回复


avatar
南霁姑娘 么么哒! 2

博主你好,如果我在新增或修改博客时body这里使用富文本编辑器,修改功能该怎么实现?目前新增页面正常显示富文本编辑器,修改页面使用textarea标签不能正常显示及使用富文本编辑器,使用{{ form.media }} {{ form.body }},旧值不知道该如何显示在页面

18天前 回复


avatar
杜赛 [博主] 南霁姑娘 么么哒! 2

cdeditor 这类插件是通过 js 进行初始化的,不能像普通的textarea标签那样给初始值。

试试直接在视图里传递初始值:

def example(request):
    ...
    ini = {'body': comment.body}
    form = CommentForm(initial=ini)
    ...

这种方法是可以的

18天前 回复


avatar
南霁姑娘 杜赛 [博主] 么么哒! 2

解决啦,谢谢博主yes

17天前 回复


avatar
ligang123 么么哒! 2
本回复已被 ligang123 删除

16天前 回复


avatar
南霁姑娘 么么哒! 2

博主你好,你这边有做评论中插入图片的功能吗smiley

14天前 回复


avatar
杜赛 [博主] 南霁姑娘 么么哒! 2

暂时不打算开放插入图片,虽然某些办法也可以插入。

ckeditor是可以上传或插入图片的,请查阅相关文档和博客

14天前 回复


avatar
南霁姑娘 杜赛 [博主] 么么哒! 2

我看您自己的博客,文章内容用markdown编写是有插入一些图片的哈,那这一块会出教程吗

13天前 回复


avatar
杜赛 [博主] 南霁姑娘 么么哒! 2

markdown 插入的都是图片链接,这个你看看 markdown 的语法说明就可以了,不需要教程啊。上传图片和上传头像是差不多的,也已经讲过了

12天前 回复


avatar
南霁姑娘 么么哒! 2
本回复已被 南霁姑娘 删除

14天前 回复


avatar
南霁姑娘 么么哒! 2
本回复已被 南霁姑娘 删除

14天前 回复


avatar
南霁姑娘 么么哒! 2

博主,这里加不加都能代码高亮显示呢,以下两种结果一样

'extraPlugins': ','.join(['codesnippet', 'prism', 'widget', 'lineutils']),
'extraPlugins': ','.join(['codesnippet']),

14天前 回复


avatar
pengshilin 么么哒! 1

本地环境运行没有问题,我已经部署到线上服务器,显示:

GET http://www.yunshu.space/static/ckeditor/ckeditor/plugins/prism/lib/prism/prism_patched.min.js net::ERR_ABORTED 404 (Not Found)

2

j.js?MAC=8CAB8EA1A110:1 A parser-blocking, cross site (i.e. different eTLD+1) script, http://51mld.cn/bd/query.js?vid=20000, is invoked via document.write. The network request for this script MAY be blocked by the browser in this or a future page load due to poor network connectivity. If blocked in this page load, it will be confirmed in a subsequent console message. See https://www.chromestatus.com/feature/5718547946799104 for more details.

(index):83 GET http://www.yunshu.space/static/ckeditor/ckeditor/plugins/prism/lib/prism/prism_patched.min.js net::ERR_ABORTED 404 (Not Found)

ckeditor.js:101 GET http://www.yunshu.space/static/ckeditor/ckeditor/plugins/prism/plugin.js?t=J39A net::ERR_ABORTED 404 (Not Found)

ckeditor.js:264 Uncaught Error: [CKEDITOR.resourceManager.load] Resource name "prism" was not found at "http://www.yunshu.space/static/ckeditor/ckeditor/plugins/prism/plugin.js?t=J39A". at CKEDITOR.resourceManager.<anonymous> (ckeditor.js:264) at e (ckeditor.js:259) at Array.y (ckeditor.js:259) at v (ckeditor.js:259) at ckeditor.js:260



我查看了下之前的讨论,说可以移除 prism 插件,可是移除了不就没有 代码高亮了么?

服务器上目录我检查了一遍,确定 venv/lib/site-packages/ckeditor/static/ckeditor/ckeditor/plugins/prism/lib/prism/prism_patched.min.js 路径没有问题

要怎么处理呢?

7天前 回复


avatar
杜赛 [博主] pengshilin 么么哒! 1

ckeditor 也是一个 app,最简单的方法是直接把虚拟环境中手动安装的 ckeditor plugin 的静态文件全部拷贝到项目的静态文件路径中。

我马上就会写部署的文章,到时会讲一下这个问题。

6天前 回复