公共的JS组件-告别CURD
-
urls.py
urlpatterns = [ url('^asset.html$', views.AssetView.as_view()), url('^asset-json.html$', views.AssetJsonView.as_view()), ]
-
views.py
# CBV方式 class AssetView(View): def get(self,request,*args,**kwargs): # 数据库中获取数据 return render(request, 'asset.html') class AssetJsonView(View): def get(self,request,*args,**kwargs): table_config = [ { 'q': None, 'title': '选项', 'display': True, 'text': {'content':'<input type="checkbox" />','kwargs': {}}, 'attrs': {}, }, { 'q':'id', 'title':'ID', 'display':False, 'text':{}, 'attrs':{}, }, { 'q': 'asset_type_id', 'title': '资产类型', 'display': True, # 是否显示 'text': {'content': '{n}', 'kwargs': {'n': '@@asset_type_choices', }}, 'attrs': {}, }, { # 'edit-type': 'select'可编辑时变成下拉框 'q': 'status_id', 'title': '状态', 'display': True, # 是否显示 'text': {'content': '{n}', 'kwargs': {'n': '@@status_choices',}},# 双@表示找选项里对应的内容 'attrs': {'name':'status_id','origin':'@status_id','edit-enable': 'true', 'edit-type': 'select','global-name':'status_choices'}, }, { 'q': 'idc__id', 'title': '机房ID', 'display': False, 'text': {}, 'attrs': {}, }, { 'q': 'idc__name', # 一对多跨表操作 'title': '机房', 'display': True, # 是否显示 'text': {'content': '{n}', 'kwargs': {'n': '@idc__name', }},# 一个@表示取数据库中的信息 'attrs': {'name':'idc_id','origin':'@idc__id','edit-enable': 'true', 'edit-type': 'select','global-name':'idc_choices'}, }, { 'q': 'cabinet_num', 'title': '机柜号', 'display': True, 'text': {'content':'{n}','kwargs':{'n':'@cabinet_num'}}, 'attrs': {'name':'cabinet_num','origin':'@cabinet_num','edit-enable': 'true', 'edit-type': 'input'}, }, { 'q': 'cabinet_order', 'title': '机柜位置', 'display': True, 'text': {'content': '{n}', 'kwargs': {'n': '@cabinet_order'}}, 'attrs': {}, }, { 'q': None, # 表示不去数据库取数据 'title': '操作', 'display': True, 'text': {'content': '<a href="/asset_detail-{m}.html">{n}</a>', 'kwargs': {'m':'@id','n':'详细'}}, 'attrs': {}, }, ] q_list = [] for i in table_config: if not i['q']: continue q_list.append(i['q']) data_list = Asset.objects.all().values(*q_list) data_list = list(data_list) print(data_list) # [{'id': 1, 'cabinet_num': '12B', 'cabinet_order': '1'}] result = { 'table_config':table_config, 'data_list':data_list, 'pager':''' <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#">5</a></li> ''', 'global_dict':{ 'asset_type_choices': Asset.asset_type_choices, # json处理之后,元组会变成列表 'status_choices': Asset.status_choices, 'idc_choices': list(IDC.objects.values_list('id','name')), }, } return HttpResponse(json.dumps(result)) def put(self,request,*args,**kwargs): # 没有request.post content = request.body val = json.loads(str(content,encoding='utf-8')) ret = {'status':True} return HttpResponse(json.dumps(ret))
-
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>后台管理</title> {% load staticfiles %} <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %}"/> <link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.css' %}"/> </head> <body> <div style="width: 1000px;margin: 0 auto;"> <h1>资产列表</h1> <div class="btn-group" role="group" aria-label="..."> <button id="idCheckAll" type="button" class="btn btn-default">全选</button> <button id="idReverseAll" type="button" class="btn btn-default">反选</button> <button id="idCancelAll" type="button" class="btn btn-default">取消</button> <button id="idEditMode" type="button" class="btn btn-default">进入编辑模式</button> <button type="button" class="btn btn-default">批量删除</button> <a id="idAdd" href="asset_add.html" class="btn btn-default">添加</a> <button id="idSave" type="button" class="btn btn-default">保存</button> </div> <table class="table table-bordered"> <thead id="table_th"> </thead> <tbody id="table_tb"> </tbody> </table> <ul id="idPagination" class="pagination"> </ul> </div> <script src="{% static 'js/jquery-3.3.1.js' %}"></script> <script src="{% static 'js/nbList.js' %}"></script> <script> $(function () { $.NB('/asset-json.html'); }); </script> </body> </html>
-
公共JS组件:主要是调用扩展方法NB
(function () { var requestUrl = null; //绑定分页事件 function bindChangePager(){ $('#idPagination').on('click','a',function () { var pageNum = $(this).text(); init(pageNum); }) } //保存 function bindSave() { $('#idSave').click(function () { //找到有hasEdit属性的tr标签 var postList = []; $('#table_tb').find('tr[has-edit="true"]').each(function () { //$(this)=tr var temp = { /* 'id':1, 'status':1, 'order':12,*/ }; temp['id'] = $(this).attr('row-id'); $(this).children('[edit-enable="true"]').each(function () { //$(this)=td var name = $(this).attr('name'); //'name':'cabinet_num' var origin = $(this).attr('origin'); var newVal = $(this).attr('new-val'); if(origin != newVal){ temp[name] = newVal; //'idc_id':2 新的select的value } }); postList.push(temp); }); $.ajax({ url:requestUrl, type:'PUT', data:{'post_list':JSON.stringify(postList)}, dataType: 'JSON', success:function (arg) { if(arg.status){ init(1); //初始化到第一页 }else{ alert(arg.error); } } }) }) } //全选 function bindCheckAll() { $('#idCheckAll').click(function () { $('#table_tb').find(':checkbox').each(function () { if($('#idEditMode').hasClass('btn-warning')){ if($(this).prop('checked')){ //如果当前行已经进入了编辑模式 }else{ trIntoEditMode($currentTr = $(this).parent().parent()); $(this).prop('checked',true); } }else{ $(this).prop('checked',true); } }) }) } //取消 function bindCancelAll() { $('#idCancelAll').click(function () { $('#table_tb').find(':checked').each(function () { if($('#idEditMode').hasClass('btn-warning')){ $(this).prop('checked',false); //取消选中,并退出编辑模式 trOutEditMode($(this).parent().parent()); }else{ $(this).prop('checked',false); } }); }) } //反选 function bindReverseAll() { $('#idReverseAll').click(function () { $('#table_tb').find(':checkbox').each(function () { if($('#idEditMode').hasClass('btn-warning')){ if($(this).prop('checked')){ //如果已经进入编辑模式,选中的要取消,再退出编辑 $(this).prop('checked',false); trOutEditMode($(this).parent().parent()); }else{ //如果已经进入编辑模式,未选中的要选中,再进入编辑 $(this).prop('checked',true); trIntoEditMode($(this).parent().parent()); } }else{ if($(this).prop('checked')){ $(this).prop('checked',false); }else{ $(this).prop('checked',true); } } }) }) } //点击进入或退出编辑模式 function bindEditMode(){ $('#idEditMode').click(function () { if($(this).hasClass('btn-warning')){ //退出编辑模式 $(this).removeClass('btn-warning'); $(this).text('进入编辑模式'); //找到所有选中的tr,进入编辑模式 $('#table_tb').find(':checked').each(function () { var $currentTr = $(this).parent().parent(); trOutEditMode($currentTr); }) }else{ //进入编辑模式 $(this).addClass('btn-warning'); $(this).text('退出编辑模式'); //找到所有选中的tr,退出编辑模式 $('#table_tb').find(':checked').each(function () { var $currentTr = $(this).parent().parent(); trIntoEditMode($currentTr); }) } }) } //委托绑定:如果用ajax在页面上添加了一行数据,会自动绑定这个事件 function bindCheckbox(){ $('#table_tb').on('click',':checkbox',function () { if($('#idEditMode').hasClass('btn-warning')){ var ck = $(this).prop('checked'); var $currentTr = $(this).parent().parent(); //变量前带$的表示为jQuery对象,只是自己看着方便 if(ck){ //选中状态,进入编辑,给tr加上背景色 trIntoEditMode($currentTr); }else{ trOutEditMode($currentTr); } } }) } //选中,进入编辑模式 function trIntoEditMode($tr){ $tr.addClass('success'); $tr.attr('has-edit','true'); // 只要进入过编辑状态的,都加上这个属性 $tr.children().each(function () { //$(this)就是tr的每一个孩子td var editEnable = $(this).attr('edit-enable'); //检查当前是否是可编辑模式 var editType = $(this).attr('edit-type'); if(editEnable == 'true'){ //可以进入编辑模式 if(editType == 'select'){ //生成下拉框 var globalName = $(this).attr('global-name'); //global-name = status_choices var origin = $(this).attr('origin'); //1 //生成select标签 var selectTag = document.createElement('select'); selectTag.className = 'form-control'; $.each(window[globalName],function (k1,v1) { var optionTag = document.createElement('option'); optionTag.setAttribute('value',v1[0]); optionTag.innerHTML = v1[1]; $(selectTag).append(optionTag); }); $(selectTag).val(origin); $(this).html(selectTag); }else if(editType == 'input'){ //生成input框 var innerText = $(this).text(); var tag = document.createElement('input'); tag.className = 'form-control'; tag.style.width = '100%'; tag.value = innerText; $(this).html(tag); } } }) } //取消选中,退出编辑模式 function trOutEditMode($tr){ $tr.removeClass('success'); $tr.children().each(function () { //$(this)就是tr的每一个孩子td var editEnable = $(this).attr('edit-enable'); //检查当前是否可编辑 var editType = $(this).attr('edit-type'); if(editEnable == 'true'){ //如果是可编辑的 if(editType == 'select'){ //如果是select框 var $select = $(this).children().first(); //jQuery对象 var newId = $select.val(); //选中的option的id var newText = $select[0].selectedOptions[0].innerHTML;//选中的option的text $(this).html(newText); //用文本替换原来的select框 $(this).attr('new-val',newId); //设置新的value值 }else{ var inputVal = $(this).children().first().val(); //获取input的值 $(this).html(inputVal); $(this).attr('new-val',inputVal); } } }) } //自定义string方法,字符串格式化 String.prototype.format = function (kwargs) { return this.replace(/\{(\w+)\}/g,function (km,m) { return kwargs[m]; }) }; //初始化 function init(pager) { $.ajax({ url:requestUrl, type:'GET', data:{pager:pager}, //把请求的页码告诉后台 dataType:'JSON', success:function (result) { initGlobalData(result.global_dict); initHeader(result.table_config); initBody(result.table_config,result.data_list); initPager(result.pager); } }) } //初始化分页 function initPager(pager) { $('#idPagination').html(pager); } //初始化表头生成<tr><th>ID</th></tr> var tr = document.createElement('tr'); function initHeader(table_config) { $('#table_th').empty(); ////先清空所有的tr,再添加tr $.each(table_config,function (k,item) { //k是列表索引,item是字典 if(item.display){ th = document.createElement('th'); th.innerHTML=item.title; $(tr).append(th); } }); console.log(tr); $('#table_th').append(tr); } //初始化tbody内容 function initBody(table_config,data_list) { $('#table_tb').empty(); //先清空,再添加 $.each(data_list,function (k,row) { //row={'id': 1, 'cabinet_num': '12B', 'cabinet_order': '1'} var tr = document.createElement('tr'); tr.setAttribute('row-id',row['id']); //生成tr标签时,就把行ID传给它,日后更新时根据这个ID更新 $.each(table_config,function (i,colConfig) { /*{ 'q': 'cabinet_num', 'title': '机柜号', 'display': True, 'text': {'content':'{n}-{m}','kwargs':{'n':'机柜','m':'@xx'}}, 'sttrs': {'edit-enable': 'true', 'edit-type': 'select'} }*/ if(colConfig.display){ var td = document.createElement('td'); //table_config.text={'content': '{n}-{m}', 'kwargs': {'n': '机柜', 'm': '@xx'}}, //colConfig.q是数据库中的字段名 //生成td的文本信息 var kwargs = {}; $.each(colConfig.text.kwargs,function (key,value) { if(value.substring(0,2) == '@@'){ //两个@@开头的,把选项ID转换成内容 var globalName = value.substring(2,value.length);//全局变量的名称 var currentId = row[colConfig.q]; //获取的数据库中存储的数字类型值 var t = getText(globalName,currentId); //根据ID去全局变量中找对应内容 kwargs[key] = t; }else if(value[0]=='@'){ //以@开头的就只取@后面的字段的值 kwargs[key] = row[value.substring(1,value.length)]; }else { kwargs[key] = value; } }); var temp = colConfig.text.content.format(kwargs); td.innerHTML = temp; //设置td的属性colConfig.attrs = {'origin':'@status_id','edit-enable': 'true', 'edit-type': 'select'}, $.each(colConfig.attrs,function (kk,vv) { if(vv[0] == '@'){ //vv=@status_id td.setAttribute(kk,row[vv.substring(1,vv.length)]);//origin=1 }else{ td.setAttribute(kk,vv); } }); tr.append(td); } }); $('#table_tb').append(tr); }); } //设置全局变量,初始化下拉框里的选择项 function initGlobalData(global_dict) { $.each(global_dict,function (k,v) { //设置全局变量 window[k] = v; }) } //根据ID获取全局变量里对应内容 var ret = null; function getText(globalName,currentId) { //globalName='asset_type_choices' //currentId=1 $.each(window[globalName],function (k,item) { if(currentId == item[0]){ ret = item[1]; return } }); return ret; } //扩展方法 jQuery.extend({ 'NB':function (url) { requestUrl = url; init(); bindEditMode(); bindCheckbox(); bindCheckAll(); bindCancelAll(); bindReverseAll(); bindSave(); bindChangePager(); }, 'changePager':function (num) { init(num); } }); })();