Django quickly integrates rich text editor wangeditor

Django is an excellent web development framework for the python stack, and it is also the development framework with the highest proportion among the python stack web development frameworks. As for whether it is good enough, it is self-evident. The built-in management background orm function is also very powerful, with a few lines of simple configuration. You can quickly have a powerful management background. The only shortcoming is that it does not integrate a rich text editor. Of course, there are many third-party packages that provide the function of integrating rich text editors, but the maintenance does not seem to be very active, and the upgrade is not very Positive, so on, I chose to integrate my own rich text editor on my django-happy-shop project!

Since I mentioned the django-happy-shop project, I have the cheek to ask everyone for a star. The open source code is hosted on Gitee, and you can find it by searching for the name. Welcome to experience the start and try it out.

HappyShop is a third-party package developed by Django, developed with django + DRF + vue, with front-end and back-end separation genes, complete multi-specification commodity logic, integrated Alipay payment, and fast collection with simple configuration. It can be quickly integrated into Any django project to quickly get a simple mall functionality.

Closer to home, why choose wangeditor?

First of all, it is because it is a very good rich text editor developed by Chinese people. It supports native JS integration and Vue and other excellent front-end framework integration. The documentation is also very complete. The most important thing is that the Chinese documentation is easy to read, the configuration is simple and clear, and it is easy to use. , and open source is free!

WeChat screenshot_20220406102338.png

start integration

Model data description

There is a field content of product details in the product model, and the selected field is TextFiled, as shown below:

content = models.TextField("Product Details")

In China, we implement the background management function admin.pythrough inheritance , as shown below, you can see the source code for detailsModelAdmin

@admin.register(HappyShopSPU)
class HappyShopSPUAdmin(HappyShopAdmin):
    '''Admin View for HappyShopSPU'''
    list_display = ('get_title', 'get_main_picture',
          'get_category', 'brand', 'is_new', 'sort', 'add_date')
复制代码

Through this code, we have registered the model with the admin management background!

我们集成wangeditor富文本编辑器采用原生JS引入的方法来进行引入,那么首先就需要把相关的JS文件引入到模板文件中,django的ModelAdmin为了提供了一个Media的源类来把js文件及css文件注册到模板中,如下所示:

@admin.register(HappyShopSPU)
class HappyShopSPUAdmin(HappyShopAdmin):
    '''Admin View for HappyShopSPU'''
    list_display = ('get_title', 'get_main_picture',
            'get_category', 'brand', 'is_new', 'sort', 'add_date')
    ....

    class Media:
        js = (
            'admin/js/vendor/jquery/jquery.min.js',
            'https://cdn.jsdelivr.net/npm/wangeditor@latest/dist/wangEditor.min.js',
            'happy_shop/js/weditor.js'
        )
复制代码

第一个JS文件看名称就知道我们先引入了django默认自带的jquery文件;第二个外链cdn的js连接是wangeditor提供的编辑器js文件;第三个weditor.js的文件是我们自己写的配置文件,前端主要的集成配置功能都集中在weditor.js文件中!内容如下:

$(document).ready(function () {
    // 创建富文本编辑器元素节点
    var wehtml = "<div id='wangcontent'></div>"
    // 获取的div
    var field_div = document.querySelectorAll(".field-content>div")
    field_div[0].insertAdjacentHTML('afterbegin', '<b>商品详情:</b>');
    field_div[0].insertAdjacentHTML('beforeend', wehtml);
    $(".field-content>div>label").attr('style', 'display:none')
    
    const E = window.wangEditor
    const editor = new E("#wangcontent")
    // 或者 const editor = new E( document.getElementById('div1') )
    const $text1 = $('#id_content')
    console.log($text1.val())
    editor.config.onchange = function (html) {
        // 第二步,监控变化,同步更新到 textarea
        $text1.val(html)
    }

    editor.config.height = 500
    // 配置 server 接口地址
    editor.config.uploadImgServer = '/happy/upload_img/'
    editor.config.uploadFileName = 'spuImg'
    editor.create()
    editor.txt.html($text1.val())
    // 第一步,初始化 textarea 的值
    $text1.val(editor.txt.html())
    $text1.attr("style","display:none")
    
})
复制代码

这段代码我就不做过多的解读,只详细说一下思路,首先我们都知道django的表单默认会有一个id的属性,属性值是以id_字段的形式组合,因此上我们就只需要把富文本编辑器的内容赋值给id_content的输入框即可正常提交,总的逻辑就是这样,剩下的就是奔着这个目的去实现!

首先我们找到富文本编辑的块,位于一个.field-content的模块当中,找到这个区块,再在这个区块中用js的方式插入一个富文本的元素<div id='wangcontent'></div>,然后参照wangeditor的文档集成富文本编辑器,并且监听编辑器的onchange事件,把富文本编辑器的内容同步赋值到表单id_content,这里有一个需要注意的是如果原本添加的内容,在编辑的时候应该也要回显到富文本编辑器,所以说这里一定要处理,注意这句editor.txt.html($text1.val())就是解决这个问题,之后把原本的输入框加入属性style设置displaynone隐藏即可!

其他代码,直接参考wangeditor的文档,写的很清楚!

实现图片上传功能

js文件中与上传图片相关的配置就以下两句:

// 配置 server 接口地址
editor.config.uploadImgServer = '/happy/upload_img/'
editor.config.uploadFileName = 'spuImg'
复制代码

第一句是图片的上传地址url;第二句是自定义表单的name值;

The view code corresponding to the upload url is as follows. You can see the code for the specific logic, which may be clearer than the text description. This restricts the need to log in to upload. If it is further restricted, we can only limit the authority of the super tube [this is improving the authority] , but I did not do this, nor did I limit the upload file type, because the rich text editor has set the size and type of the image by default in the previous section. Of course, the value passed from the front end should never be trusted as the back end. Its verification, this will also be processed in later versions, all extracted into the configuration file of the project!

class HappyShopUploadImage(LoginRequiredMixin, View):
    """富文本编辑器上传图片
    首先会检查项目根目录有没有media/upload/的文件夹
    如果没有就创建,图片最终保存在media/upload/目录下
    返回图片路径为 "/media/upload/file.png"
    wangEditor_v4文档:https://www.wangeditor.com/
    """
    
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)
    
    def post(self, request, *args, **kwargs):
        import os
        import uuid
        file_data = request.FILES
        keys = list(file_data.keys())
        file_path = settings.BASE_DIR / 'media/upload/'
        if os.path.exists(file_path) is False:
            os.mkdir(file_path)
        # 返回数据中需要的data
        data = []
        for key in keys:
            img_dict = {}
            file = file_data.get(f'{key}')
            # 重命名文件名称
            names = list(os.path.splitext(file.name))
            names[0] = ''.join(str(uuid.uuid4()).split('-'))
            file.name = ''.join(names)
            new_path = os.path.join(file_path, file.name) 
            # 开始上传
            with open(new_path, 'wb+') as f:
                for chunk in file.chunks():
                    f.write(chunk)
            # 构造返回数据
            img_dict['url'] = f'/media/upload/{file.name}'
            data.append(img_dict)
        context = {"errno": 0,"data":data}
        return JsonResponse(context)
复制代码

Finally, add the view url to the url file of the application, as follows:

path('upload_img/', views.HappyShopUploadImage.as_view(), name="upload_img")
复制代码

At this point, our rich text editor has been successfully integrated. If you have any questions, you can leave a message for consultation, or look at the source code directly! Don't forget to star!

Guess you like

Origin juejin.im/post/7083396244927676424