• 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'); //
//生成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);
}
});
})();

公共的JS组件-告别CURD的更多相关文章

  1. JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(三):两个Viewmodel搞定增删改查

    前言:之前博主分享过knockoutJS和BootstrapTable的一些基础用法,都是写基础应用,根本谈不上封装,仅仅是避免了html控件的取值和赋值,远远没有将MVVM的精妙展现出来.最近项目打 ...

  2. vue.js组件化开发实践

    前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎么实现,技术选型自然 ...

  3. JS组件系列——封装自己的JS组件,你也可以

    前言:之前分享了那么多bootstrap组件的使用经验,这篇博主打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么自定义自己的组件,比如我们想扩展一 ...

  4. JS组件系列——封装自己的JS组件

    前言:之前分享了那么多bootstrap组件的使用经验,这篇博主打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么自定义自己的组件,比如我们想扩展一 ...

  5. VUE.JS组件化

    VUE.JS组件化 前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎 ...

  6. JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(一)

    前言:出于某种原因,需要学习下Knockout.js,这个组件很早前听说过,但一直没尝试使用,这两天学习了下,觉得它真心不错,双向绑定的机制简直太爽了.今天打算结合bootstrapTable和Kno ...

  7. JS组件系列——BootstrapTable 行内编辑解决方案:x-editable

    前言:之前介绍bootstrapTable组件的时候有提到它的行内编辑功能,只不过为了展示功能,将此一笔带过了,罪过罪过!最近项目里面还是打算将行内编辑用起来,于是再次研究了下x-editable组件 ...

  8. JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(四):自定义T4模板快速生成页面

    前言:上篇介绍了下ko增删改查的封装,确实节省了大量的js代码.博主是一个喜欢偷懒的人,总觉得这些基础的增删改查效果能不能通过一个什么工具直接生成页面效果,啥代码都不用写了,那该多爽.于是研究了下T4 ...

  9. JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)

    前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...

随机推荐

  1. [MV] - You Give REST a Bad Name

    本首歌改自Bon Jovi经典歌曲"You Give Love a Bad Name". 改编的作者是Dylan Beattie, 他是Spotlight的系统架构师. 改编后的歌 ...

  2. Java核心技术及面试指南 多线程并发部分的面试题总结以及答案

    7.2.10.1有T1.T2.T3三个线程,如何保证T2在T1执行完后执行,T3在T2执行完后执行? 用join语句,在t3开始前join t2,在t2开始前join t1. 不过,这会破坏多线程的并 ...

  3. WebSocket(4)---实现定时推送比特币交易信息

    实现定时推送比特币交易信息 实现功能:跟虚拟币交易所一样,时时更新当前比特币的价格,最高价,最低价,买一价等等...... 提示:(1)本篇博客是在上一遍基础上搭建,上一篇博客地址:[WebSocke ...

  4. SpringCloud(2)---SpringCloud入门篇

    SpringCloud理解篇 一.微服务概述 1.什么是微服务 目前的微服务并没有一个统一的标准,一般是以业务来划分将传统的一站式应用,拆分成一个个的服务,彻底去耦合,一个微服务就是单功能业务,只做一 ...

  5. Android应用系列:仿MIUI的Toast动画效果实现(有图有源码)

    前言 相信有些人用过MIUI,会发现小米的Toast跟Android传统的Toast特么是不一样的,他会从底部向上飞入,然后渐变消失.看起来效果是挺不错的,但是对于Android原生Toast是不支持 ...

  6. Java基础13:反射详解

    本节主要介绍Java反射的原理,使用方法以及相关的技术细节,并且介绍了关于Class类,注解等内容. 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech ...

  7. linux添加C#运行环境

    linux是不带C#的运行环境的,同样的还有.NET. 有一个叫做Mono的很好用http://www.go-mono.com/,有给docker,而且有环境的选择,要注意. 安好后有给样例的程序,编 ...

  8. .NET快速信息化系统开发框架 V3.2 -> Web 用户管理模块编辑界面-组织机构选择支持级联选择

    下拉框级联选择功能非常的实用,框架用户管理编辑界面对组织机构的选择在3.2版本中新增了级联选择的支持,让组织机构的选择更加的方便与高效,也不容易出错. 我们框架的组织机构结合实际分成了5种类型,分别为 ...

  9. Spring Boot 2.x(七):优雅的处理异常

    前言 异常的处理在我们的日常开发中是一个绕不过去的坎,在Spring Boot 项目中如何优雅的去处理异常,正是我们这一节课需要研究的方向. 异常的分类 在一个Spring Boot项目中,我们可以把 ...

  10. #8 Python网络编程(一)

    前言 语言是用来交流的,人类语言使人与人交流,编程语言使人与机器交流,那么问题来了,机器如何与机器交流.你是否疑惑过:为什么我们可以使用浏览器查资料.为什么我们可以使用聊天软件聊天.为什么我们可以通过 ...