在django项目中集成trix编辑器

背景

公司基于adminset框架做运维管理系统,需要一个页面来记录有关运维管理系统的基本概念、开发思路及用法。自告奋勇接了开发这个wiki模块的活。由于目前需要显示的内容不多,wiki模块就两个页面,一个编辑wiki,一个展示内容。

总结

通过这个集成项目,学到的技能有

  1. 熟悉了django的model,view,url,form,templates流程和用法。
  2. 了解并实现了Ajax传递信息。
  3. 了解了django文件上传的设置方式。

过程

在页面上编辑文章,需要用到编辑器,不然就是一个多行单元格。

v0.1

  1. 输入页面由一个多行输入框构成,内容中带markdown标签,存储入数据库。
  2. 展示页面获取带标签的文章,用解释器解释为正确格式的html文档。
    使用的插件为 Stack Overflow 上评论用的插件 pagedown 。调试js有点绕,看demo后成功调用插件。存在的缺点有1)图片不支持,2)不能所见即所得。有点:存储带标签的文档,可以由不同markdown解释器转换为html。

v0.2

使用trix编辑器-trix编辑器 ,此编辑器是 37signals 团队2018年5月开源的。此团队写了 Ruby on Rails 框架,redo,rework 两本书。
显示页面引入trix的js和css后,直接显示

1
2
3
4
5
6
7
8
9
10
11
<head>
<link rel="stylesheet" type="text/css" href="/static/css/trix.css">
<script type="text/javascript" src="/static/js/trix.js"></script>
</head>
<body>
<div class="trix-content">
 {% autoescape off %}
{{ article.content }}
{% endautoescape %}
</div>
</body>

编辑页面

1
2
3
4
5
6
7
8
9
<link rel="stylesheet" type="text/css" href="/static/css/trix.css">
<script type="text/javascript" src="/static/js/trix.js"></script>

<form action="{% url 'edit_homepage' %}" method="POST">
{% csrf_token %}
<input id="id_content" type="hidden" name="content" value="{{ article.content }}">
<trix-editor input="id_content" class="trix-content"></trix-editor>
<input type="submit" value="save" >
</form>

要实现拖拽或ctrl V 添加图片,需要AJAX脚本。attachment.js
将图片传递给后端,传递成功后根据url生成规则设置当前图片的url

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
     (function() {
var HOST = "/wiki/upload_ajax";

addEventListener("trix-attachment-add", function(event) {
if (event.attachment.file) {
uploadAttachment(event.attachment)
}
});

function uploadAttachment(attachment) {
var file = attachment.file;
var name = createStorageKey(file);
var form = new FormData();
form.append('img',file);
form.append('name',name);
var xhr = new XMLHttpRequest();
xhr.open("POST", HOST, true);

xhr.upload.addEventListener("progress", function(event) {
var progress = event.loaded / event.total * 100
attachment.setUploadProgress(progress)
})

xhr.addEventListener("load", function(event) {
if (xhr.status == 200) {
attachment.setAttributes({ url: [ "/media/img",name].join("/") })
}
})

xhr.send(form);
}

function createStorageKey(file) {
var date = new Date()
var day = date.toISOString().slice(0,10)
var name = date.getTime() + "-" + file.name
// return [ "/media","img", day, name ].join("/")
return name
}

function createFormData(key, file) {
var data = new FormData()
data.append("key", key)
data.append("file", file)
data.append("Content-Type", file.type)
return data
}
})();

处理ajax请求的的函数,将js传递的文件,保存在数据库,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@csrf_exempt
def upload_ajax(request):
temp_name = "wiki/wiki-header.html"
if request.method == 'POST':
#print (request.FILES.get('img').name)
img_name = request.POST.get('name')
#print (request.POST.get('name'))
new_img = IMG(
img = request.FILES.get('img'),
name = request.POST.get('name')
)
new_img.img.name = request.POST.get('name')
new_img.save()
#img_url = IMG.objects.get(name=img_name).img.url
#print img_url
#return img_url

return render(request,'wiki/edit_homepage.html',locals())

效果

image.png | left | 747x379

image.png | left | 747x199

参考

https://www.cnblogs.com/14061216chen/p/6537864.html django传图片
http://www.cnblogs.com/ccorz/p/5912478.html ajax原理