0. 前言
- 需求来源
开发适合公司的CRM系统,供客服和营销人员使用 - 开发工具
Django框架 - 本文内容
在Web页面点击呼叫按钮时,向数据库中插入一条通话记录
关于Django
和MVC
的概念和一些基础知识我就不讲了,在这放几个参考文章吧。
Django框架基础全面讲解参考来源:
Django框架全面讲解Django框架的理解与Django开发过程的总结Django官方文档Django源码文档Django官方文档中文
本文主要讲的是,在本项目中,代码上的调用和运行流程。因为搜了一下,讲解概念的比较多,具体项目实现的代码就不多了,在开发过程中也遇到了很多的问题,这算是个入门吧。
还是觉得要针对需求和问题来学习的更快,所以本文也是在已经有大神开发完初版后的基础上,根据一个功能需求来进行解剖。很多地方没提到,只关注本需求的实现。
1. 总体流程
放一张参考博文中的运行流程图:
再放一张我自己乱画的,乱七八糟的图。。。。(可能只有我自己看得懂了)
代码结构如下:
接下来,我就按照我完成的一个功能来进行讲解。
希望能把自己讲明白。。。。
2. 需求及思路
2.1 需求
对数据进行脱敏;
在拨打电话界面,点击呼叫时,生成一条拨打记录,包括此时的客服id,客户id,拨打开始时间等,插入 user_call_history 数据表中,然后点击挂机时,更新该条记录的拨打结束时间;
2.2 思路
2.2.1 数据脱敏
针对数据脱敏很容易可以想到有两种方式,在前端进行或者在后端进行,要是在前端进行,可以参考下面这种 js 函数:
function handle(param){
var strlen = param.length;
if(strlen < 9){
return strlen;
}
return param..replace(/^(.{6})(?:\d+)(.{4})$/,"$1******$2");
}
当然这种方式也很明显不安全,毕竟数据都已经取出来了,无非是在前端掩盖了一下,我还是采用了后端脱敏的方式,从源头解决问题。
那么问题来了,后端数据是咋取到的呢,又是在哪对其进行处理呢,这就是要Django进行探索的地方了。
2.2.2 点击事件
- 要实现在前端点击按钮,则涉及交互事件,要在前端(template)中写入交互事件(js);
- 点击后,要往数据表中插入数据,则要先看看该数据库存不存在(model);
- 将前端触发事件和后端数据库连接的桥梁(url 映射);
- 那么插入表中的字段和数据又是如何获取的呢?
3. 数据脱敏
我要进行脱敏的数据在外呼管理(apps/call模块)中。
要对客户姓名及后续的银行卡号进行脱敏,好,那我就去寻找call模块,可以看到以下代码:
这里看的出来,是很典型的 Django 框架,再提一下,从 url 配置映射,然后就会去views 中寻找函数/类,结合 models 中的数据和 template 的界面,渲染成页面。
可以看到,这里比Django官方教程中多了两个文件api.py``serializers.py
,在此解释一下,本项目中,并没有直接在 views 文件中直接装配 template 和 model,而是在中间加了个api,多了一步而已,api的功能基本就是正常的 views功能。
至于 serializers 文件,有点网络基础的同学应该可以猜到,这是一个序列化文件。
算了,估计说了也不懂,要是懂的话估计也不会看到我这篇博文了 哈哈哈。
放心,接下来用到就会懂了。
3.1 model层查看
我们知道,model是和数据库对应的,所以可以从model下手,去看看数据是如何取出来的,再去研究如何进行脱敏。
这里的数据记录来源于数据库中的 customer_info表,那我就去model.py中找相关的model。
model找到了,按照Django框架的设计,应该是views.py中从model中取数,再给template组装,但是上面说了,本项目中使用了一个api.py将model与template进行隔离。
那就去看看api.py中看看是啥玩意儿吧。
3.2 views功能
仔细一点的话,一进去就可以看到导入了我们想要的model:
from call.models import CustomerInfo,
有戏! 那就 find 一下,看看在哪用了。
可以看到这样的一个类,这里为了讲解明白,删减了一部分,够讲清楚就行。
这里第一次看可能有点懵,它的效果就是在进入显示界面时,获得前端要显示的字段和数值,也就是下图中,第一行是字段,第二行是从数据库获得的数值,至于前端如何联系起来的待会再讲,现在就是联系起来了。
显示列表一般用 get 方法,于是这些字段都是作为参数直接放在url中的,例如:
/call/api/listCustomer/?/call/api/listCustomer?username=&real_name=&channel_name=&user_category=&user_status=&last_bookings_time
=&_=1557751142607
所以下面这一句
username = Utiles.getQueryParam(request.query_params, 'username')
就是获得上图中的“用户名”这个字段,由于参数太多,所以用了一个字典 kwargs来存储这些参数而已。
重头戏来了,看这一句:
customerInfos = CustomerInfo.objects.filter(**kwargs).order_by('-last_bookings_time')
这里,就是利用model,从数据库中取出查询结果,可能换成下面这样的语句看要更清楚一些:
customerInfos = CustomerInfo.objects.filter(user_id=user_id,user_name=user_name,real_name=real_name,channel_name=channel_name)
customerInfos = customerInfos.order_by('-last_bookings_time')
关于objects.filter,这里我就不讲太多了,基础教程去看看就知道了,就看成是SQL语句就行了,最后得到结果集,是QuerySet对象,为可迭代对象。
后面的order by是不是特别熟悉啊,对,就是字面的意思,加个’-'表示逆序,也就是desc操作,所以啊,这里就是在获取了前端要查询的字段后,传参给model,得到查询的结果集,然后进行过滤啊,排序啊啥的。
所以啊,这个customerInfos就是我们展示的结果集,要进行的脱敏字段也在这个里面了,比如real_name。
先对其进行脱敏吧,既然知道了是QuerySet对象,而且是可迭代对象,那咱就来吧。
# 对真实姓名和银行卡号进行脱敏处理,只显示姓和最后四位卡号
for i in range(len(customerInfos)):
real_name_mark = ['*' for i in range(len(customerInfos[i].real_name) - 1)]
bank_no_mark = ['*' for i in range(len(customerInfos[i].bank_no) - 4)]
real_name_mark = "".join(real_name_mark)
bank_no_mark = "".join(bank_no_mark)
customerInfos[i].real_name = customerInfos[i].real_name[0] + real_name_mark
customerInfos[i].bank_no = bank_no_mark + customerInfos[i].bank_no[-4:]
这样,就从查询到的数据集中就直接把数据进行脱敏了,无论前端怎么展示,也不怕被人抓包之类的了。
3.3 url 映射
刚才说了model层建表,说了 view层(api.py)返回结果集,那么接下来要说的就是前端(template)如何与后台联系起来了。
还是按照Django框架的设计来看,从url 映射看起,可以看到熟悉的ListCustomer,只不过这里加了一个asView
方法,
这样就把view和url连接起来了,输入这个url,就会去调用ListCustomer类,那么该类里用的辣么多参数又是如何从前端传到这个类里面来的呢。
我们去看看前端的html代码。
3.4 template层传参数
在这里面搜一下api/listCustomer
,看看哪里连接起来的。看到这样一段 ajax 代码。
这里可以看到,设置了url ,也设置了 http 方式为 get,得到的数据为 search-form里面的。
再在里面看看有没有啥熟悉的东西?对,有id="username" name="username"
,这个,就是刚才api中,get方法username = Utiles.getQueryParam(request.query_params, 'username')
中的username啊。
该js函数首先将url映射到 api/listCustomer,然后将search-form中的参数进行序列化(serialize()),以GET方式进行HTTP传输参数,然后两者在view(api.py)里汇合,就去model取相应的数据。
同时,在刚才那个ajax代码中,还有这样一段代码,
这里就是在前端界面展示的数据表格字段和属性。
3.5 捋一捋
这么看下来,还是有点乱哈,主要就是前后端啊,前端页面,后端数据。