urlpatterns = [
url('^asset.html$', views.AssetView.as_view()),
url('^asset-json.html$', views.AssetJsonView.as_view()),
]
# 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))
<!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>
(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);
}
});
})();