后台管理
1. 访问过程
我们在前面2天得到了各个客户端的资产数据信息,我们将各个这个数据打包发送到api,这个api其实就是django的url传参,之后按照数据的格式对比数据库增删改
2. 后台页面显示数据1
首先我们来通通思路
当用户发来get请求,我需要展示资产列表给用户,那我处理get请求,给视图去数据库中匹配内容,最后展示在页面上,我们采用ajax提交
我们最开始得到如下数据格式 table_config
table_config = [{ 'q': 'id', # 数据库查询条件 'title': 'ID', # 前端页面显示 'display': False, # 是否在前端显示 },]
然后我们从数据库中根据q的查询条件筛选出内容 data_list,最后将上面 table_config 和 data_list 传给前端
# 数据库中拿到data_list q_list = [] for i in table_config: q_list.append(i['q']) from repository import models data_list = models.Asset.objects.all().values(*q_list) data_list = list(data_list) # 格式化数据 result = { 'table_config':table_config, 'data_list':data_list,} return HttpResponse(json.dumps(result))
前端拿到table_config 和 data_list 会根据里面的key来判断显示什么,内容是什么?
3. 后台页面显示数据2
很显然上面的数据并不很理想,因为显示的内容都只是数据库里面的,我只能对它做一些显示不显示的操作,如果说我要在显示的内容上进行格式化数据,每一行数据后面加一个操作就需要如下格式
table_config = [{ 'q':'cabinet_order', 机柜号 'title':'机柜号', 'dispaly':TRUE, 显示 'text':{'content':"{n}-{m}",'kwargs':{'n':"机柜",'m':'xxx'}} # 自己随便写的字符串进行格式化 }, { 'q': None, 'title': '操作', # 指的是,查看信息,编辑等 'display': True, 'text': {'content': "<a href='/assetdetail-{m}.html'>{n}</a>",'kwargs': {'n': '查看详细','m': '@id'}},
@ 表示从数据库查询(data_list)的字段,并不是自己随便写的字符串格式化 'attrs': {}, } }]
然后我们从数据库中根据q的查询条件筛选出内容 data_list,最后将上面 table_config 和 data_list 传给前端
# 数据库中拿到data_list q_list = [] for i in table_config: if not i['q']: # 这个表示q为NONE的时候, 不会添加到q_list里面,但是我页面需要显示这个操作,从而引入text 相比上面的数据,这里新加 continue q_list.append(i['q']) from repository import models data_list = models.Asset.objects.all().values(*q_list) data_list = list(data_list) print(data_list) # 格式化数据 result = { 'table_config':table_config, 'data_list':data_list, } return HttpResponse(json.dumps(result))
js字符串格式化方式如下

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> /* 在原型里面自定义方法 String.prototype.format = function (kwargs) { // this ="laiying: {age} - {gender}"; // kwargs = {'age':18,'gender': '女'} var ret = this.replace(/{(w+)}/g,function (km,m) { return kwargs[m]; }); return ret; }; // 自定义joker格式化 == joker == format var v = "laiying: {age} - {gender}"; var result = v.shizhengwen({'age': 18, 'gender': '女'}); console.log(result); */ String.prototype.joker = function (kwargs) { console.log(this); // mokey,因为是monkey调用的这个方法,this就是调用当前方法的对象,String {"monkey:{age}-{sex}"} // this 'monkey:{age}-{sex}' // kwargs {'age':18,'sex':'women'} // 字符串格式化 var ret = this.replace(/{(w+)}/g, function (km, m) { // km 带括号的所有匹配项 m 是在km的基础上拿到分组的内容 console.log(km, m); // {age} age {sex} sex return kwargs[m] // kwargs[age] kwargs[sex] }); // 将 KM {age} 替换成 kwargs[m] == value return ret; }; var s = 'monkey:{age}-{sex}'; var result = s.joker({'age': 18, 'sex': 'women'}); console.log(result); // monkey:18-women // 就会打印ok alert(result) </script> </body> </html>
前端拿到table_config 和 data_list 会根据里面的key来判断显示什么,内容是什么?
4. 后台页面显示数据3
上面的数据还不是很理想,因为表字段里面还有choice类型,外键,显示字段的标签属性等,所以我们在上面的基础上增加一些格式如下
table_config = { 'q': 'device_type_id', 'title': '资产类型', # choice ,我们要显示的应该是中文而不是数字 'display': True, # @@ 表示 chioce 'text': {'content': "{n}",'kwargs'{'n':"@@device_type_choices"}}, 'attrs': {} # 标签属性 }, { 'q': 'idc__name', # 外键 'title': 'IDC', 'display': True, 'text': {'content': "{n}", 'kwargs': {'n': "@idc__name"}}, attrs': {} }
然后我们从数据库中根据q的查询条件筛选出内容 data_list,最后将上面 table_config 和 data_list 传给前端
# 数据库中拿到data_list q_list = [] for i in table_config: if not i['q']: # 这个表示q为NONE的时候, 不会添加到q_list里面,但是我页面需要显示这个操作,从而引入text continue q_list.append(i['q']) from repository import models data_list = models.Asset.objects.all().values(*q_list) data_list = list(data_list) print(data_list) # 格式化数据 result = { 'table_config':table_config, 'data_list':data_list, 'global_dict': { # choices 类型 'device_type_choices': models.Asset.device_type_choices, 'device_status_choices': models.Asset.device_status_choices } } return HttpResponse(json.dumps(result))
5. 前端代码

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>资产列表</h1> <table border="1"> <thead id="table_th"></thead> <tbody id="table_tb"></tbody> </table> <script src="/static/js/jquery-1.12.4.js"></script> <script> {# 访问这里就会加载这个匿名函数#} $(function () { init(); }); // 字符串格式化,详情件test.html String.prototype.format = function (kwargs) { // this ="laiying: {age} - {gender}"; // kwargs = {'age':18,'gender': '女'} var ret = this.replace(/{(w+)}/g, function (km, m) { return kwargs[m]; }); return ret; }; {# 发送ajax请求给asset-json.html#} function init() { $.ajax({ url: '/web/asset-json.html', type: 'GET', dataType: 'JSON', success: function (result) { // 这是需要判断@ @@ initGlobalData(result.global_dict); // 资产头部 initHeader(result.table_config); // 资产内容 initBody(result.table_config, result.data_list) } }) } {# 资产显示头部#} function initHeader(table_config) { /* table_config = [ { 'q': 'id', 'title': 'ID', 'display':false }, { 'q': 'name', 'title': '随便', 'display': true } ] */ /* <tr> <th>ID</th> <th>用户名</th> </tr> */ var tr = document.createElement('tr'); $.each(table_config, function (k, item) { if (item.display) { var th = document.createElement('th'); th.innerHTML = item.title; $(tr).append(th); } }); $('#table_th').append(tr); } {# 资产显示内容部#} function initBody(table_config, data_list) { console.log(table_config); console.log(data_list); // 这个循环多少行 $.each(data_list, function (k, row) { // data_list 信息,机柜信息,q查询获取的 row = {'cabinet_num': '12B', 'cabinet_order': '1', 'id': 1}, var tr = document.createElement('tr'); // 这个循环多少列,而列的内容都可以在row里面取到 $.each(table_config, function (i, colConfig) { console.log(colConfig); /* colConfig 内容 { 'q':'id', 'title':'ID', 'dispaly':FALSE, 不显示 } { 'q':'cabinet_num', 'title':'机柜号', 'dispaly':TRUE, 显示 } */ console.log('aaaaaaaaaaaaaaaaaaaaaaa'+colConfig.display); console.log(colConfig.text.content); if (colConfig.display){ // 之前不考虑 操作 的时候 // 列内容就是colconfig.q var td = document.createElement('td'); // colconfig.q ==> 'cabinet_num' // td.innerHTML = row[colconfig.q] // $(tr).append(td); // 我们考虑到操作 加入了text // colconfig.text 'text':{'content':"{n}-{m}",'kwargs':{'n':"机柜",'m':'xxx'}} // colconfig.text.content "{n}-{m}" // colconfig.text.kwargs {'n':"机柜",'m':'@xxx'} // str.strip lenth python // js字符串叫string类型 string.length // string.prototype 所有字符串方法都在这里面,这叫原型 测试文件是test.html /* 生成文本信息 @ 表示从数据库取,没有@表示就用该字符串*/ var kwargs = {}; console.log('0000'); $.each(colConfig.text.kwargs, function (key, value) { // @@ 如果是@@ 表示 是chioce if (value.substring(0, 2) == '@@') { var globalName = value.substring(2, value.length); // 全局变量的名称 var currentId = row[colConfig.q]; // 获取的数据库中存储的数字类型值 var t = getTextFromGlobalById(globalName, currentId); kwargs[key] = t; } // 表示以@开头,切割 1=-1,不要第一个@字符,要后面的 xx else if (value[0] == '@') { kwargs[key] = row[value.substring(1, value.length)]; //cabinet_num } else { kwargs[key] = value; } }); console.log(1111); console.log(222); // 字符串格式化 console.log(colConfig.text.content); var temp = colConfig.text.content.format(kwargs); td.innerHTML = temp; /* 属性colConfig.attrs = {'edit-enable': 'true','edit-type': 'select'} */ $.each(colConfig.attrs, function (kk, vv) { td.setAttribute(kk, vv); }); $(tr).append(td); } }); $('#table_tb').append(tr); }); } /* * [ * {'cabinet_num': '12B', 'cabinet_order': '1', 'id': 1}, * {'cabinet_num': '12B', 'cabinet_order': '1', 'id': 1}, * ] * * <tr> <td>12B</td> <td>1</td> </tr> <tr> <td>12C</td> <td>1</td> </tr> * * */ // 解决 choioce 数字转中文,全局 function initGlobalData(global_dict) { $.each(global_dict, function (k, v) { // k = "device_type_choices" // v= [[0,'xx'],[1,'xxx']] // 设置全局变量的三种写法 {# device_type_choices = 123;#} {# window.v = 123;#} window[k] = v; }) } // q 查询得到数字,在跟全局的比对,然后得出结果 function getTextFromGlobalById(globalName, currentId) { // globalName = "device_type_choices" // currentId = 1 var ret = null; // 全局变量 "device_type_choices":[[0,'xx'],[1,'xxx']] $.each(window[globalName], function (k, item) { console.log(item[0], item[1], currentId); if (item[0] == currentId) { ret = item[1]; return // 终止each 循环 } }); return ret; } </script> </body> </html>