zl程序教程

您现在的位置是:首页 >  其他

当前栏目

Django添加ckeditor富文本编辑器

2023-02-18 16:37:51 时间

源码 https://github.com/django-ckeditor/django-ckeditor

通过pip安装。

pip3 install django-ckeditor
pip3 install Pillow

在settings.py的INSTALLED_APPS里添加ckeditor和ckeditor_uploader两个应用。

INSTALLED_APPS = (
    #
    'ckeditor',
    'ckeditor_uploader'
)

在settings.py里进行ckeditor的相关配置。

CKEDITOR_JQUERY_URL = 'https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js'  
MEDIA_URL = '/media/'  
MEDIA_ROOT = os.path.join(BASE_DIR,'media/')  
CKEDITOR_UPLOAD_PATH = 'uploads/'  
CKEDITOR_IMAGE_BACKEND = 'pillow'  
CKEDITOR_CONFIGS = {  
    'default': {  
        'toolbar': 'full',  
        'height':600,
        'width':800,
    },  
} 

接下来在urls.py里配置ckeditor相关的url。

from django.conf import settings
from django.conf.urls.static import static
from django.conf.urls import url,include

urlpatterns = [
      url(r'^ckeditor/', include('ckeditor_uploader.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)  # 没有这一句无法显示上传的图片

最后修改需要使用富文本编辑器的Django APP的目录下的models.py。其中RichTextField拥有TextField的全部参数,还拥有其他的一些参数。

from ckeditor.fields import RichTextField
#
content = RichTextField() # 将需要使用富文本编辑器的字段改为RichTextField
from ckeditor_uploader.fields import RichTextUploadingField
    content = RichTextUploadingField(verbose_name=u'内容')#可以上传图片的

在 templates 中使用内容

{{ content | safe }}  

django使用ckeditor上传图片

1、在模型类中设置字段为富文本类型,这里需要注意引入的是RichTextUploadingField,以允许上传图片,需要和RichTextField区分开

from ckeditor_uploader.fields import RichTextUploadingField
class spit_model(models.Model):
    """模型类"""
    user = models.ForeignKey(User, on_delete=models.CASCADE,verbose_name='吐槽发布者')
    content = RichTextUploadingField(verbose_name='吐槽内容', max_length=200)

2、项目中ckeditor的安装及配置

pip install django-ckeditor
INSTALLED_APPS = [
    ...
  'ckeditor',  # 富文本编辑器
  'ckeditor_uploader',  # 富文本编辑器上传图片模块
    ...
]
# 富文本编辑器ckeditor配置
CKEDITOR_CONFIGS = {
    'default': {
        'toolbar': 'full',  # 工具条功能
        'height': 300,  # 编辑器高度
        'width': 300,  # 编辑器宽
    },
}

 CKEDITOR_UPLOAD_PATH = ''  # 图片ckeditor文件上传路径,这里使用七牛云存储,不填

2、html页面中加入textarea标签

<div>
<textarea  id="editor_id"></textarea>
</div>

3、页面中引入控制html页面的JS和ckeditor的JS文件, 在django的installed_app中注册应用时,会自动在虚拟环境中生成应用信息/home/python/.virtualenvs/django_1.11.16_py3/lib/python3.5/site-packages/ckeditor/static/ckeditor/ckeditor/

在js路径前加上域名,否则服务器会在live-server的默认端口下进行网络通讯,查找js
<script type="text/javascript" src="js/spit-submit.js"></script>
<script src="http://127.0.0.1:8000/static/ckeditor/ckeditor/ckeditor.js"></script> 

4、在vue变量的mounted方法中加入

let vm = new Vue({
  ...
    mounted:function () {
        CKEDITOR.replace('editor_id', { filebrowserUploadUrl:'http://127.0.0.1:8000/ckeditor/upload/' }); // 将id选择器的文本域替换成为富文本,并手动设置文件上传的请求路径,默认请求路径为live-server的路径,必须设置为服务器的域名和端口
    },
});

5、后端设置总路由,'ckeditor_uploader.urls'中会将接收到的请求进行csrf校验免除,并限制了只有登录用户才可以上传图片,ckeditor默认应用的是django-admin的用户校验方法,django-admin的校验方法不允许跨域请求,我们需要使上传图片的类试图函数继承自django-restframework的APIVIew,

   # url(r'^ckeditor/', include('ckeditor_uploader.urls')),  # 为富文本编辑器添加总路由
    # url(r'^ckeditor/upload/', ImageUploadView.as_view()),  # 为富文本编辑器添加总路由
    # url(r'^ckeditor/upload/', csrf_exempt(ImageUploadView.as_view())),  # 为富文本编辑器添加总路由
    url(r'^ckeditor/', csrf_exempt(ImageUploadView.as_view())),  # 为富文本编辑器添加总路由

6、在应用中改写路由和类视图,使用permission_classes对请求权限进行限制

# 配置路由
urlpatterns = [
    url(r'^upload/$', ImageUploadView.as_view()),
]


from ckeditor_uploader import image_processing,utils
from django.conf import settings
from django.http import HttpResponse
from django.http import JsonResponse
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from django.utils.html import escape


class ImageUploadView(APIView):
    permission_classes = [IsAuthenticated]
    http_method_names = ['post']

    def post(self, request, **kwargs):
        """
        Uploads a file and send back its URL to CKEditor.
        """
        uploaded_file = request.FILES['upload']

        backend = image_processing.get_backend()

        ck_func_num = request.GET.get('CKEditorFuncNum')
        if ck_func_num:
            ck_func_num = escape(ck_func_num)

        # Throws an error when an non-image file are uploaded.
        if not getattr(settings, 'CKEDITOR_ALLOW_NONIMAGE_FILES', True):
            try:
                backend.image_verify(uploaded_file)
            except utils.NotAnImageException:
                return HttpResponse("""
                    <script type='text/javascript'>
                    window.parent.CKEDITOR.tools.callFunction({0}, '', 'Invalid file type.');
                    </script>""".format(ck_func_num))

        saved_path = self._save_file(request, uploaded_file)
        if len(str(saved_path).split('.')) > 1:
            if(str(saved_path).split('.')[1].lower() != 'gif'):
                self._create_thumbnail_if_needed(backend, saved_path)
        url = utils.get_media_url(saved_path)

        if ck_func_num:
            # Respond with Javascript sending ckeditor upload url.
            return HttpResponse("""
            <script type='text/javascript'>
                window.parent.CKEDITOR.tools.callFunction({0}, '{1}');
            </script>""".format(ck_func_num, url))
        else:
            retdata = {'url': url, 'uploaded': '1',
                       'fileName': uploaded_file.name}
            return JsonResponse(retdata)

一. 如何添加中文字体?

CKEditor安装后默认的情况下只有英文字体的选择,如果想添加中文字体,则找到ckeditor下的配置文件config.js. 在CKEDITOR.editorConfig = function( config ) 这句话后面的大括号就是"{ }"的第一行加上如下代码:

config.font_names = config.font_names + '微软雅黑;宋体;黑体;仿宋_GB2312;楷体_GB2312;隶书;幼圆;' ;

保存,刷新页面就可以了!

二. 如何设置默认选择的字体及大小?如何设置默认使用的字体及大小?

前者,需要修改 ckeditor/contents.css 里的设置。

body
{
        /* Font */
        /*font-family: sans-serif, Arial, Verdana, "Trebuchet MS";*/
        font-family:黑体;
        font-size: 16px;

后者,两种方式:

方法一: 基于上面的操作,在修改body的字体和大小后。将.cke_editor中的有关字体的设置去掉;

方法二: 修改config.js文件,添加下面的设置:

config.fontSize_defaultLabel = '16px';
config.font_defaultLabel = '黑体';

三. CKEditor中文字体名称乱码?

第一步操作,重新加载页面,中文字体显示,但是名称却显示乱码?在虚拟机的Ubuntu上用火狐试了一把,同样的问题,可见和浏览器没有关系,问题出在服务器端。

回想下第一步的操作,在server端,直接用gvim编辑的config.js文件。事后,用:set fileencoding去查看文件编码,不是utf-8格式,怀疑。root权限下,在vim中修改文件的编码:set fileencoding=utf-8后,重新加载页面,显示正常。

四.如何高亮代码?

常用的插件有code snippet 和pbckcode,这里不做比较。仅对code snippet进行了尝试。

涉及到前端显示和后端编辑两部分。后端编辑方面,django_ckeditor-5.2.2-py2.7.egg中已经自带了code snippet插件,仅需进行简单的配置,就可以在后端激活这个插件。在项目的settings.py文件中,修改CKEDITOR_CONFIGS。

CKEDITOR_CONFIGS = {
   ...
   'more': {
        'toolbar': (
            ['Source','-','Templates','Preview','Save'],
            ['Maximize','CodeSnippet'],
            ['TextColor','BGColor'],
            ['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
            ['Cut','Copy','Paste','Print'],
            ['Undo','Redo','-','SelectAll','Find','Replace'],
            ['Styles','Format','Font','FontSize'],
            ['NumberedList','BulletedList','Blockquote'],
            ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
            ['Link','Unlink','Anchor'],
            ['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar'],
        ),
        'width' : '96%',
        'extraPlugins': "codesnippet",
    },
}

还可以设置code snippet的主题样式,在ckeditor/config.js中,修改如下,

CKEDITOR.editorConfig = function( config ) {
	...
	config.codeSnippet_theme = 'school_book';
};

此时,刷新浏览器页面,可以发现代码部分实际上没有特别变化,还和背景融为一体。这是因为前端还需要加载一些js文件和css文件。

1.Refer to codesnippet插件 Target Page,http://docs.ckeditor.com/#!/guide/dev_codesnippet

To see the highlighter styles on the target page where CKEditor content is displayed, you will need to load the highlight.js script and theme's stylesheet on this page. You can either reuse a copy of highlight.js placed in the ckeditor/plugins/codesnippet/lib/highlight directory or download your own copy from the highlight.js download page.

Attach it to the <head> section of your page. The following code will load the highlight.js library and the stylesheet for the default theme:

<head>
    ...
    <link href="ckeditor/plugins/.../styles/default.css" rel="stylesheet">
    <script src="ckeditor/plugins/.../highlight.pack.js"></script>
</head>

Inititalize highlight.js on all <pre><code> .. </code></pre> elements with the following code:

<script>hljs.initHighlightingOnLoad();</script>

所以,修改如下,

a.模板路径/blog/base.html中添加,

{% block extra_link %}
   ...
   <link href="{% static 'ckeditor/ckeditor/plugins/codesnippet/lib/highlight/styles/zenburn.css' %}" rel="stylesheet">
   ...
{% endblock %}
{% block extra_js %}
   ...
   <script src="{% static 'ckeditor/ckeditor/plugins/codesnippet/lib/highlight/highlight.pack.js' %}" type="text/javascript"></script>
   ...
{% endblock %}

b.模板路径/blog/detail.html中添加,

{% block inner_extra_js %}
   ...
   <script>hljs.initHighlightingOnLoad();</script>
{% endblock %}

c.还可以修改前端显示的css,只需将default.css替换成路径static\ckeditor\ckeditor\plugins\codesnippet\lib\highlight\styles中存在的css文件即可,比如zenburn.css

每种样式表的效果,可以看这里https://highlightjs.org/static/demo/.

d.highlight.js的使用说明,了解一下,可以进行个人定制。

https://highlightjs.org/usage/

e.修改了原先使用的一些js,备注一下。

五.Code Snippet添加的代码超长,不会自动换行,撑破了页面,如何解决?

通过CSS的方式解决。打开选择的highlight.js样式表zenburn.css,修改如下,

.hljs {
  ...
  white-space: pre-wrap !important;
}

其中的!important很重要,没加这个的时候,这个css好像不起作用,原因不明。

Refer to: http://www.ieclipse.cn/en/2016/07/18/Web/Hexo-dev-highlight/index.html

六.添加后的文章,在显示全文的时候,如何合理自动换行?

七.Tab键的使用,默认按Tab会移出编辑框,如何解决?

config.tabSpaces = 0;
设置当用户键入TAB键时,鼠标走过的空格数。当值为0时,焦点将移出编辑框。

八.使用序列标号的时候,页面溢出?

OL/UL的CSS样式表,padding-left导致的,解决方法,可以修改前端页面的样式表。

是否有其他更好的解决方法?假设后端的CKEditor已经添加好样式表了?

九.前端页面显示的字体/大小和后端设置的不一样?

前端页面CSS造成的,如何解决?

十.使用七牛云存储,缩略图无法生成?

CKEDITOR_IMAGE_BACKEND = 'PIL'
or
CKEDITOR_IMAGE_BACKEND = 'pillow'

从code上看,只有配置成'pillow'时才会生成缩略图。PIL在ckeditor中是dummy_backend,在相应的py文件中可以看到,它恒返回False。

def should_create_thumbnail(file_path):
    return False

还有一个问题,七牛storage读取图片有错误。

def should_create_thumbnail(file_path):
    image = default_storage.open(file_path)
    try:
        Image.open(image)
    except IOError:
        return False
    else:
        return utils.is_valid_image_extension(file_path)
ckeditor_uploader\ image\ pillow_backend.py should_create_thumbnail file_path is  uploads/keaiduo/2017/10/22/404test.png , default_storage is  <qiniustorage.backends.QiniuMediaStorage object at 0x7f300343d450>
ckeditor_uploader\ image\ pillow_backend.py should_create_thumbnail IOError