CURD
CURD是一个数据库技术中的缩写词,一般的项目开发的各种参数的基本功能都是CURD。作用是用于处理数据的基本原子操作。
它代表创建(Create)、更新(Update)、读取(Retrieve)和删除(Delete)操作。
核心
1.前端页面通过ajax方式请求后台数据库数据
2.后台 配置文件 指定字段去数据库取相应的字段返回给前端ajax
3.前端通过jquery 实现前端页面数据修改,将修改数据再次通过ajax返回给后台
具体实现
前端ajax获取数据
在js自执行函数中,写入代码,定义全局变量 requestURL,方便后面传入新的ajax 提交路径,以ajax以get方式去后台获取数据. 获取到后台 result 数据,将其传递到 对应函数执行
requestURL = null; function init(pager) {
$.ajax(
{
url:requestURL,
data:{'pager':pager},
type:'GET',
dataType:'JSON',
success:function (result) {
initchoice(result.choice_dict);
initheader(result.table_config);
initbody(result.table_config,result.info) }
}
)
};
定义配置文件(整合 前端/数据库数据/显示样式)
在后台 视图页面定义一个配置文件:
数据结构为: 列表[字典方式]
id , 作为数据库中的字段.
title,前端显示的字段名
display,是否在前端显示
text,在前端可定义显示内容
attrs,样式定义,提交name定义,修旧数值定义,文本类型定义(input?select?其他)
table_config = [
{
'id': None,
'title': '选项',
'display': 1,
'text': {'key': "<input type='checkbox' />", 'val': {}},
'attrs': {},
},
{
'id':'id',
'title':'ID',
'display':1,
'text':{'key':"{n}",'val':{'n':'@id'}},
'attrs':{},
},
{
'id': 'title',
'title': '标题',
'display': 1,
'text': {'key': "{n}", 'val': {'n': '@title'}},
'attrs': {'name':'title',"origin":'@title','edit-enable':'true','edit-type':'input'},
},
{
'id': 'status',
'title': '状态',
'display': 1,
'text': {'key': "{n}", 'val': {'n': '@@device_type_choice'}},
'attrs': {'name':'status',"origin":'@status','edit-enable':'true','edit-type':'select',"global-name":'device_type_choice'},
},
{
'id': 'pro_id',
'title': '处理人',
'display': 1,
'text': {'key': "{n}", 'val': {'n': '@@device_type_userinfo'}},
'attrs': {'name':'pro_id',"origin":'@pro_id','edit-enable':'true','edit-type':'select',"global-name":'device_type_userinfo'},
},
{
'id': 'sol',
'title': '处理详情',
'display': 1,
'text': {'key': "{n}", 'val': {'n': '@sol'}},
'attrs': {'name': 'sol', "origin": '@sol', 'edit-enable': 'true', 'edit-type': 'input'},
},
{
'id': None,
'title': '操作',
'display': 1,
'text': {'key': "<a href='#'>添加</a>|<a href='#'>删除</a>", 'val': {}},
'attrs': {},
},
]
数据库表(贴出来做参考的,上面只是截取了表中部分字段显示)
class Fault(models.Model):
id = models.AutoField(primary_key=True,null=False)
title = models.CharField(max_length=20,verbose_name="报障标题")
detail = models.TextField(verbose_name="报障详细信息")
user_id = models.ForeignKey('Userinfo',
to_field='uid',
on_delete=models.CASCADE,
verbose_name="报障人",
related_name='u')
choice = (
(1, '待处理'),
(2, '处理中'),
(3, '已处理'),
)
status = models.IntegerField(choices=choice,verbose_name='处理状态',default=1)
ctime = models.DateTimeField(null=False, auto_now_add=True, verbose_name='创建时间')
pro = models.ForeignKey('Userinfo',
to_field='uid',
on_delete=models.CASCADE,
verbose_name="处理人",
null=True,
blank=True,
related_name='p',
)
sol = models.TextField(null=True,verbose_name="解决方案")
ptime = models.DateTimeField(null=True)
获取冲数据库中获取指定字段数据
视图将配置文件中id字段循环出来加入到zd列表列表中,然后去数据库中取指定字段的数据,将其整合到result字典中,转为json字符串传递到 前端ajax 回到函数中.
def ajaxdate(request):
import json
if request.method == "GET":
table_config = [...]
zd = []
for i in table_config:
if i['id']:
zd.append(i['id'])
info = models.Fault.objects.values(*zd).all()
choice = models.Fault.choice
userinfo = models.Userinfo.objects.all().values_list('uid','uname') result = {
'table_config':table_config,
'info':list(info),
'choice_dict':{'device_type_choice':choice,'device_type_userinfo':list(userinfo)},
} return HttpResponse(json.dumps(result))
ajax回到执行函数(显示表头、显示主体数据、添加html全局变量)
这样就将后台的表头,数据都显示到前端
// {#列表表头显示部分#}
function initheader(table_config) {
var tr = document.createElement('tr');
$.each(table_config,function (k,item) {
var th = document.createElement('th');
if (item.display){
th.innerHTML = item.title;
$(tr).append(th);
}
});
$('#table_th').empty();
$('#table_th').append(tr);
} // {#列表数据显示部分#}
function initbody(table_config,info){
$('#table_td').empty();
$.each(info,function (i,j) {
var tr = document.createElement('tr');
tr.setAttribute('j-id',j['id']);
var dictinfo = {};
$.each(table_config,function (x,y) {
if (y.display) {
$.each(y.text.val,function (k,v) {
if(v.substring(0,2) ==='@@'){
var gname = v.substring(2,v.length);
var gid = j[y.id];
var t = test(gname,gid);
dictinfo[k] =t; }else if (v[0] ==='@'){
dictinfo[k] = j[v.substring(1,v.length)];
}else {
dictinfo[k] = v;}
});
var td = document.createElement('td');
var ss = y.text.key.format(dictinfo);
td.innerHTML = ss; $.each(y.attrs,function (q,t) {
if(t[0] === '@'){
td.setAttribute(q,j[t.substring(1,t.length)]);
}else {
td.setAttribute(q,t)
}
}); $(tr).append(td);}
});
$('#table_td').append(tr)})} // {#choice数据类型,定义全局变量#}
function initchoice(choice_dict) {
$.each(choice_dict,function (i,j) {
window[i]=j;
})
} // {#将以数据id去choice全局变量取对应的 中文显示信息#}
function test(gname,gid) {
var ret = null;
$.each(window[gname], function (k, item) {
if (item[0] === gid) {
ret = item[1];
return
}
});
return ret;
}
前端html 添加操作按钮
<h1>用户信息</h1>
<div class="btn-group" role="group" aria-label="...">
<button id="bindall" type="button" class="btn btn-default">全选</button>
<button id="bindfx" type="button" class="btn btn-default">反选</button>
<button id="unbindall" type="button" class="btn btn-default">取消</button>
<button id="bindbj" type="button" class="btn btn-default">进入编辑模式</button>
<button type="button" class="btn btn-default">批量删除</button>
<button id='save' type="button" class="btn btn-default">保存</button>
</div>
<table class="table table-bordered table-hover">
<thead id="table_th"></thead>
<tbody id="table_td"></tbody>
</table>
自定义format字符串方法
// {#自定义的 字符format的方法#}
String.prototype.format = function(kwargs){
var ret = this.replace(/\{(\w+)\}/g,function (k,m) {
return kwargs[m]
});
return ret
};
用jquery绑定事件
function bindsave(){
$('#save').click(function () {
var postlist=[];
$('#table_td').find('tr[has-edit="true"]').each(function () {
var temp = {};
var id = $(this).attr('j-id');
temp['id'] = id;
$(this).children('[edit-enable="true"]').each(function () {
var name = $(this).attr('name');
var origin = $(this).attr('origin');
var newval = $(this).attr('new-val');
if(origin != newval){
temp[name] = newval;
};
})
postlist.push(temp);
$.ajax({
url:requestURL,
type:'POST',
data:{'post_list':JSON.stringify(postlist)},
dataType:'Json',
success:function (arg) {
if(arg.status){
init(1);
}else {
alter(arg);
}
} }) }) })
}
function bindM() {
$('#bindbj').click(function () {
var ed = $(this).hasClass('btn-warning');
if(ed){
$(this).removeClass('btn-warning');
$(this).text("进入编辑模式");
$('#table_td').find(':checked').each(function () {
var $cur = $(this).parent().parent();
bjhangout($cur);
})
}else {
$(this).addClass('btn-warning');
$(this).text("退出编辑模式");
$('#table_td').find(':checked').each(function () {
var $cur = $(this).parent().parent();
bjhang($cur);
})
}
})
}
function bindC() {
// {#$('#table_td').find(':checkbox').click()
// 这种方式新增数据无法被选中#}
$('#table_td').on('click',':checkbox',function () {
if($('#bindbj').hasClass('btn-warning')){
var ck = $(this).prop('checked');
var $cur = $(this).parent().parent();
if(ck){
// {#console.log("进入编辑模式");#}
bjhang($cur)
}else{
// {#console.log("退出编辑模式");#}
bjhangout($cur)
}
}
})
}
function bjhang(cur) {
cur.attr('has-edit','true');
cur.children().each(function () {
cur.addClass('success');
var editenable = $(this).attr('edit-enable');
var editetype = $(this).attr('edit-type');
if (editenable === 'true'){
if(editetype === 'select'){
var globalname = $(this).attr("global-name");
var origin = $(this).attr("origin");
var sel = document.createElement('select');
sel.className = "form-control";
$.each(window[globalname],function (k,v) {
var op = document.createElement('option');
op.innerHTML = v[1];
op.setAttribute('value',v[0]);
$(sel).append(op)
});
$(sel).val(origin);
$(this).html(sel); }else if(editetype === 'input'){
var intext = $(this).text();
var tag = document.createElement('input');
tag.className = "form-control";
tag.value = intext;
$(this).html(tag)
}
}})}
function bjhangout(cur) {
cur.removeClass('success');
cur.children().each(function () {
var editenable = $(this).attr('edit-enable');
if (editenable === 'true'){
var editetype = $(this).attr('edit-type');
if(editetype === 'select'){
var $select = $(this).children().first() ;
var newid = $select.val();
var newtext = $select[0].selectedOptions[0].innerHTML;
$(this).html(newtext);
$(this).attr('new-val',newid) }else if(editetype === 'input'){
var $input2 = $(this).children().first() ;
var tag2 = $input2.val();
$(this).html(tag2);
$(this).attr('new-val',tag2) }}})}
function bindall() {
$('#bindall').click(function () {
$('#table_td').find(':checkbox').each(function () {
if($('#bindbj').hasClass('btn-warning')){
if($(this).prop('checked')){ }else {
$(this).prop('checked',true);
var $cur = $(this).parent().parent();
bjhang($cur)
}
}else {
$(this).prop('checked',true);
};
})
})
}
function unbindall() {
$('#unbindall').click(function () {
$('#table_td').find(':checked').each(function () {
if($('#bindbj').hasClass('btn-warning')){
$(this).prop('checked',false);
var $cur = $(this).parent().parent();
bjhangout($cur);
}else {
$(this).prop('checked',false);
}
})
})
}
function bindfx() {
$('#bindfx').click(function () {
$('#table_td').find(':checkbox').each(function () {
if($('#bindbj').hasClass('btn-warning')){
var $cur = $(this).parent().parent();
if ($(this).prop('checked')){
$(this).prop('checked',false);
bjhangout($cur);
}else {
$(this).prop('checked',true);
bjhang($cur);
}
}else {
if ($(this).prop('checked')){
$(this).prop('checked',false);
}else {
$(this).prop('checked',true);
}
}
})
})
}
完整代码
html - 模板
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
{# <title>Title</title>#}
<!--单独子版的title-->
<title>{% block title %}{% endblock %}</title> <!--单独子版的css-->
{% block css %}{% endblock %}
<style>
.item{ }
.title{
font-size: 20px;
}
.content{
margin-left: 30px;
}
.content a{
display: block;
}
</style>
<link type="text/css" rel="stylesheet" href="/static/css/muban-css.css">
<link rel="stylesheet" href="/static/font-awesome-4.7.0/font-awesome-4.7.0/css/font-awesome.min.css">
</head>
<body> {#头部 start#}
<div class="pg-header">
<!--共享的-->
{#头部菜单导航条#}
<div class="logo left">Anec后台管理</div>
<div class="hl-menu left">
<a href="#" class="item">菜单一</a>
<div class="item-set">
<a href="#" class="item">菜单二</a>
<div class="sets hide">
<a href="#" >菜单二1</a>
<a href="#" >菜单二2</a>
<a href="#" >菜单二3</a>
</div>
</div>
<div class="item-set">
<a href="#" class="item">菜单三</a>
<div class="sets hide">
<a href="#" >菜单三1</a>
<a href="#" >菜单三2</a>
<a href="#" >菜单三3</a>
</div>
</div>
<div class="item-set">
<a href="#" class="item">菜单四</a>
<div class="sets hide">
<a href="#" >菜单四1</a>
<a href="#" >菜单四2</a>
<a href="#" >菜单四3</a>
</div>
</div> </div>
{#个人消息通知栏#}
<div class="hr-menu right">
<a href="#" class="item"><i class="fa fa-envelope" aria-hidden="true"></i>消息</a>
<a href="#" class="item"><i class="fa fa-phone-square" aria-hidden="true"></i>通知</a>
<a href="#" class="item"><i class="fa fa-server" aria-hidden="true"></i>任务</a>
<div class="avatar">
<a href="#" class="item">
{# <img src="111.jpg" >#}
<i class="fa fa-user-circle-o fa-2x" aria-hidden="true"></i>
</a>
<div class="sets hide">
<a href="#" >菜单1</a>
<a href="#" >菜单2</a>
<a href="#" >菜单3</a>
</div>
</div> </div>
</div>
{#头部 end#} {#div_body start #}
<div class="pg-body">
{#body-菜单栏 start#}
<div class="menus">
<!--共享的-->
<div class="item">
<div class="item-title"><a>功能1</a></div>
<div class="item-content ">
<a href="/clbzd-ck">报障单</a>
<a>功能1-2</a>
<a>功能1-3</a>
</div>
</div>
{% block menu %}{% endblock %}
</div>
{#body-菜单栏 end#} {#body-内容栏 start#}
<div class="countents">
<!--单独显示的-->
<div class="countents-top"> </div>
<div class="countent">
{% block countent %}{% endblock %}
</div>
</div>
{#body-内容栏 end#}
</div>
{#div_body end #} {#div foot start#}
<div class="pg-foot">
<!--共享的-->
</div>
{#div foot end#} <!--单独子版js-->
{% block js %}{% endblock %} </body>
</html>
html 代码
{% extends "htmb.html" %} {% block css %}
<link rel="stylesheet" href="/static/bootstrap/bootstrap-3.3.7-dist/css/bootstrap.min.css">
{% endblock %} {% block js %}
<script src="/static/js/jquery-1.7.1.min.js"></script>
<script src="/static/js/cmdbzj.js"></script>
<script>
$(function () {
$.NB( '/ajax-date.html')
}) </script>
{% endblock %} {% block title %}
{% endblock %} {% block menu %}
{% endblock %} {% block countent %}
<h1>用户信息</h1>
<div class="btn-group" role="group" aria-label="...">
<button id="bindall" type="button" class="btn btn-default">全选</button>
<button id="bindfx" type="button" class="btn btn-default">反选</button>
<button id="unbindall" type="button" class="btn btn-default">取消</button>
<button id="bindbj" type="button" class="btn btn-default">进入编辑模式</button>
<button type="button" class="btn btn-default">批量删除</button>
<button id='save' type="button" class="btn btn-default">保存</button>
</div>
<table class="table table-bordered table-hover">
<thead id="table_th"></thead>
<tbody id="table_td"></tbody>
</table>
{% endblock %}
封装的JS代码
// 自执行函数
(function () {
requestURL = null; // {#自定义的 字符format的方法#}
String.prototype.format = function(kwargs){
var ret = this.replace(/\{(\w+)\}/g,function (k,m) {
return kwargs[m]
});
return ret
}; function bindsave(){
$('#save').click(function () {
var postlist=[];
$('#table_td').find('tr[has-edit="true"]').each(function () {
var temp = {};
var id = $(this).attr('j-id');
temp['id'] = id;
$(this).children('[edit-enable="true"]').each(function () {
var name = $(this).attr('name');
var origin = $(this).attr('origin');
var newval = $(this).attr('new-val');
if(origin != newval){
temp[name] = newval;
};
})
postlist.push(temp);
$.ajax({
url:requestURL,
type:'POST',
data:{'post_list':JSON.stringify(postlist)},
dataType:'Json',
success:function (arg) {
if(arg.status){
init(1);
}else {
alter(arg);
}
} }) }) })
}
function bindM() {
$('#bindbj').click(function () {
var ed = $(this).hasClass('btn-warning');
if(ed){
$(this).removeClass('btn-warning');
$(this).text("进入编辑模式");
$('#table_td').find(':checked').each(function () {
var $cur = $(this).parent().parent();
bjhangout($cur);
})
}else {
$(this).addClass('btn-warning');
$(this).text("退出编辑模式");
$('#table_td').find(':checked').each(function () {
var $cur = $(this).parent().parent();
bjhang($cur);
})
}
})
}
function bindC() {
// {#$('#table_td').find(':checkbox').click()
// 这种方式新增数据无法被选中#}
$('#table_td').on('click',':checkbox',function () {
if($('#bindbj').hasClass('btn-warning')){
var ck = $(this).prop('checked');
var $cur = $(this).parent().parent();
if(ck){
// {#console.log("进入编辑模式");#}
bjhang($cur)
}else{
// {#console.log("退出编辑模式");#}
bjhangout($cur)
}
}
})
}
function bjhang(cur) {
cur.attr('has-edit','true');
cur.children().each(function () {
cur.addClass('success');
var editenable = $(this).attr('edit-enable');
var editetype = $(this).attr('edit-type');
if (editenable === 'true'){
if(editetype === 'select'){
var globalname = $(this).attr("global-name");
var origin = $(this).attr("origin");
var sel = document.createElement('select');
sel.className = "form-control";
$.each(window[globalname],function (k,v) {
var op = document.createElement('option');
op.innerHTML = v[1];
op.setAttribute('value',v[0]);
$(sel).append(op)
});
$(sel).val(origin);
$(this).html(sel); }else if(editetype === 'input'){
var intext = $(this).text();
var tag = document.createElement('input');
tag.className = "form-control";
tag.value = intext;
$(this).html(tag)
}
}})}
function bjhangout(cur) {
cur.removeClass('success');
cur.children().each(function () {
var editenable = $(this).attr('edit-enable');
if (editenable === 'true'){
var editetype = $(this).attr('edit-type');
if(editetype === 'select'){
var $select = $(this).children().first() ;
var newid = $select.val();
var newtext = $select[0].selectedOptions[0].innerHTML;
$(this).html(newtext);
$(this).attr('new-val',newid) }else if(editetype === 'input'){
var $input2 = $(this).children().first() ;
var tag2 = $input2.val();
$(this).html(tag2);
$(this).attr('new-val',tag2) }}})}
function bindall() {
$('#bindall').click(function () {
$('#table_td').find(':checkbox').each(function () {
if($('#bindbj').hasClass('btn-warning')){
if($(this).prop('checked')){ }else {
$(this).prop('checked',true);
var $cur = $(this).parent().parent();
bjhang($cur)
}
}else {
$(this).prop('checked',true);
};
})
})
}
function unbindall() {
$('#unbindall').click(function () {
$('#table_td').find(':checked').each(function () {
if($('#bindbj').hasClass('btn-warning')){
$(this).prop('checked',false);
var $cur = $(this).parent().parent();
bjhangout($cur);
}else {
$(this).prop('checked',false);
}
})
})
}
function bindfx() {
$('#bindfx').click(function () {
$('#table_td').find(':checkbox').each(function () {
if($('#bindbj').hasClass('btn-warning')){
var $cur = $(this).parent().parent();
if ($(this).prop('checked')){
$(this).prop('checked',false);
bjhangout($cur);
}else {
$(this).prop('checked',true);
bjhang($cur);
}
}else {
if ($(this).prop('checked')){
$(this).prop('checked',false);
}else {
$(this).prop('checked',true);
}
}
})
})
} // {#用ajax get方式获取后台的json数据#}
function init(pager) {
$.ajax(
{
url:requestURL,
data:{'pager':pager},
type:'GET',
dataType:'JSON',
success:function (result) {
initchoice(result.choice_dict);
initheader(result.table_config);
initbody(result.table_config,result.info)
}
}
)
}; // {#列表表头显示部分#}
function initheader(table_config) {
var tr = document.createElement('tr');
$.each(table_config,function (k,item) {
var th = document.createElement('th');
if (item.display){
th.innerHTML = item.title;
$(tr).append(th);
}
});
$('#table_th').empty();
$('#table_th').append(tr);
} // {#列表数据显示部分#}
function initbody(table_config,info){
$('#table_td').empty();
$.each(info,function (i,j) {
var tr = document.createElement('tr');
tr.setAttribute('j-id',j['id']);
var dictinfo = {};
$.each(table_config,function (x,y) {
if (y.display) {
$.each(y.text.val,function (k,v) {
if(v.substring(0,2) ==='@@'){
var gname = v.substring(2,v.length);
var gid = j[y.id];
var t = test(gname,gid);
dictinfo[k] =t; }else if (v[0] ==='@'){
dictinfo[k] = j[v.substring(1,v.length)];
}else {
dictinfo[k] = v;}
});
var td = document.createElement('td');
var ss = y.text.key.format(dictinfo);
td.innerHTML = ss; $.each(y.attrs,function (q,t) {
if(t[0] === '@'){
td.setAttribute(q,j[t.substring(1,t.length)]);
}else {
td.setAttribute(q,t)
}
}); $(tr).append(td);}
});
$('#table_td').append(tr)})} // {#choice数据类型,定义全局变量#}
function initchoice(choice_dict) {
$.each(choice_dict,function (i,j) {
window[i]=j;
})
} // {#将以数据id去choice全局变量取对应的 中文显示信息#}
function test(gname,gid) {
var ret = null;
$.each(window[gname], function (k, item) {
if (item[0] === gid) {
ret = item[1];
return
}
});
return ret;
} jQuery.extend({
'NB':function (url) {
requestURL = url;
init();
bindM();
bindC();
bindall();
unbindall();
bindfx();
bindsave();
},
'changepager':function (num) {
init(num);
}
})
})();
views完整代码
def ajaxdate(request):
import json
if request.method == "GET":
table_config = [
{
'id': None,
'title': '选项',
'display': 1,
'text': {'key': "<input type='checkbox' />", 'val': {}},
'attrs': {},
},
{
'id':'id',
'title':'ID',
'display':1,
'text':{'key':"{n}",'val':{'n':'@id'}},
'attrs':{},
},
{
'id': 'title',
'title': '标题',
'display': 1,
'text': {'key': "{n}", 'val': {'n': '@title'}},
'attrs': {'name':'title',"origin":'@title','edit-enable':'true','edit-type':'input'},
},
{
'id': 'status',
'title': '状态',
'display': 1,
'text': {'key': "{n}", 'val': {'n': '@@device_type_choice'}},
'attrs': {'name':'status',"origin":'@status','edit-enable':'true','edit-type':'select',"global-name":'device_type_choice'},
},
{
'id': 'pro_id',
'title': '处理人',
'display': 1,
'text': {'key': "{n}", 'val': {'n': '@@device_type_userinfo'}},
'attrs': {'name':'pro_id',"origin":'@pro_id','edit-enable':'true','edit-type':'select',"global-name":'device_type_userinfo'},
},
{
'id': 'sol',
'title': '处理详情',
'display': 1,
'text': {'key': "{n}", 'val': {'n': '@sol'}},
'attrs': {'name': 'sol', "origin": '@sol', 'edit-enable': 'true', 'edit-type': 'input'},
},
{
'id': None,
'title': '操作',
'display': 1,
'text': {'key': "<a href='#'>添加</a>|<a href='#'>删除</a>", 'val': {}},
'attrs': {},
},
]
zd = []
for i in table_config:
if i['id']:
zd.append(i['id'])
info = models.Fault.objects.values(*zd).all()
choice = models.Fault.choice
userinfo = models.Userinfo.objects.all().values_list('uid','uname') result = {
'table_config':table_config,
'info':list(info),
'choice_dict':{'device_type_choice':choice,'device_type_userinfo':list(userinfo)},
}
return HttpResponse(json.dumps(result)) elif request.method == "POST":
content = json.loads(request.POST['post_list'])
if content:
for i in content:
models.Fault.objects.filter(id=i['id']).update_or_create(i) ret = {'status':'OK'}
return HttpResponse('OK')
此章内容很重要,需练到自己可以脱稿写出来为止!!!!!