在前端构造表格的时候往往遇到的情况时写很多的tr和td标签,而且如果需要对数据库进行连接的话就涉及很多的表操作,很容易弄混而且出错,那么应该如何去避免类似情况的发生?
首先我们同样使用之前介绍的Django建立三个数据库,分别为UserInfo,Business和Server。如下代码所示:
from django.db import models # Create your models here. class UserInfo(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() class Business(models.Model): name = models.CharField(max_length=32) class Server(models.Model): server_type_choice = { (1,'存储'), (2,'Web'), (3,'cache'), } server_type = models.IntegerField(choices=server_type_choice) hostname = models.CharField(max_length=32) port = models.IntegerField() business=models.ForeignKey('Business') user_info = models.ForeignKey('UserInfo')
Server的数据表单比较复杂,且有外键关联,类型比较全面,那么我们就以此为例,其他两张表的操作可参考Server表单
表单设置完毕之后在url中设置访问Server的地址,并在view中创建对应类(因为涉及的都为数据类型,设置为类之后更易访问和储存)
url(r'^server.html', views.UserView.as_view()),
view中的UserView类为:
class UserView(View): def get(self,request,*args,**kwargs): return render(request,'server.html')
直接到模板语言中进行渲染,然后在网页中引用Ajax操作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1"> <thead id="thead"></thead> <tbody id="tbody"></tbody> </table> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/nb-ajax.js"></script> <script> $(function () { init() }); function init() { $.ajax({ url:'server-json.html', dataType:'JSON', type:'GET', success:function (arg) { } }) } </script> </body> </html>
此时已经基本建立表结构,只是在表中没有填充任何数据,利用Ajax的方式向serve-json.html发送了一个请求,下面的操作就是需要去如何操作数据库。
在url中以类的方式建立对应关系: url(r'^server-json.html', views.UserJsonView.as_view()),
在view中建立对应类:
1 #用于封装数据 2 class BaseResponse(object):#定义一个基类,便于创建对象和数据引用 3 def __init__(self): 4 self.status = True 5 self.data = None 6 self.message = None 7 8 class UserJsonView(View): 9 def get(self,request,*args,**kwargs):#当get请求时执行函数 10 response=BaseResponse() 11 try: 12 table_config=[ 13 { 'q':'hostname',#q对应数据库中的关键字,方便提取 14 'title':'主机名',#表头名称 15 'display':1,#是否显示 16 }, 17 { 'q':'port', 18 'title':'端口', 19 'display':1 20 }, 21 {'q': 'server_type', 22 'title': '服务器类型', 23 'display': 1 24 }, 25 {'q': 'user_info__name', 26 'title': '用户姓名', 27 'display': 1 28 }, 29 { 'q':None,#空列 30 'title':'操作', 31 'display':1 32 } 33 ] 34 value_list=[]#为了之后进行数据库关键字的筛选 35 for items in table_config:#对table_config进行循环 36 if items['q']:#如果q有数据 37 value_list.append(items['q'])#添加进表中 38 result = models.Server.objects.values(*value_list)#使用model对数据库的数据进行关键字筛选 39 data_list = list(result)#转化为列表的形式,为之后转为json形式传递回去做准备 40 response.data = {#待传递的数据 41 'table_config':table_config, 42 'data_list':data_list 43 } 44 except Exception as e:#异常判定 45 response.data = False 46 response.message = str(e)#提取异常信息 47 j=json.dumps(response.__dict__)#将数据转化为json格式 48 return HttpResponse(j)#返回给server.html
此时就可以看出在Ajax中返回的数据为一个包含了数据库数据的字典,
$.ajax({ url :url, type : 'GET', dataType : "JSON", success:function (arg) { if(arg.data){ creatTablehead(arg.data.table_config); creatTableboy(arg.data.table_config,arg.data.data_list); }else{ alert(arg.message) } } })
在ajax中插入了两个函数,创建表头函数和创建表单函数。
function creatTablehead(config) { /*config=[ { ‘p':'hostname' 'title':'主机名', 'display':0, }, ]*/ var tr = document.createElement('tr');/*生成tr*/ $.each(config,function(k,v){ if(v.display){ var th = document.createElement('th');/*生成表头th*/ th.innerHTML = v.title;/*将数据库数据赋值单元格*/ $(tr).append(th);/*将th添加到tr中*/ } $('#thead').append(tr);/*将包含数据库数据的tr添加到Thead中完成表头的创建*/ }) }
function creatTableboy(table_head,data_list) {/*分别传入表头数据和表单内容,表头数据用了判断一共有几列,循环多少次*/ $.each(data_list,function (k1,row) {/*循环每个数据库中筛选出来的数据*/ var tr = document.createElement('tr');/*同上,创建tr标签*/ $.each(table_head,function (k2,head_list) {/*循环每个表头*/ var td = document.createElement('td');/*创建td标签*/ td.innerHTML=row[head_list.q];/*让数据库中的数据按照表头所需的形式进行提取*/ $(tr).append(td); }); $('#tbody').append(tr); }) }
通过上面两个函数即完成了表头以及表单的创建。
为了进一步降低程序的耦合度,我们接下来将函数打包封装在一个js插件中,命名为list.js。代码为:
(function (jq) { function init(url) { $.ajax({ url :url, type : 'GET', dataType : "JSON", success:function (arg) { if(arg.data){ creatTablehead(arg.data.table_config); creatTableboy(arg.data.table_config,arg.data.data_list); }else{ alert(arg.message) } } }) } function creatTablehead(config) { /*config=[ { 'title':'主机名', 'display':0, }, { 'title':'端口', 'display':0, } ]*/ var tr = document.createElement('tr');/*生成tr*/ $.each(config,function(k,v){ if(v.display){ var th = document.createElement('th');/*生成表头th*/ th.innerHTML = v.title;/*将数据库数据赋值单元格*/ $(tr).append(th);/*将th添加到tr中*/ } $('#thead').append(tr);/*将包含数据库数据的tr添加到Thead中完成表头的创建*/ }) } function creatTableboy(table_head,data_list) {/*分别传入表头数据和表单内容,表头数据用了判断一共有几列,循环多少次*/ $.each(data_list,function (k1,row) {/*循环每个数据库中筛选出来的数据*/ var tr = document.createElement('tr');/*同上,创建tr标签*/ $.each(table_head,function (k2,head_list) {/*循环每个表头*/ var td = document.createElement('td');/*创建td标签*/ td.innerHTML=row[head_list.q];/*让数据库中的数据按照表头所需的形式进行提取*/ $(tr).append(td); }); $('#tbody').append(tr); }) } jq.extend({ 'format':function (url) { init(url); } }) })(jQuery);
通过此封装,之后的调用只需要写format(url)即可,则可将server.html中的scriot代码减少至三行:
$(function () { $.format('/server-json.html'); });
而且如果向重新生成别的种类的表结构,只需要更改table_config中的数据以及对应的url和类,方法跟server类似,而且改动很小,在前端代码中甚至只需要改动一个url即可,极大的方便未来的调用和拓展。
class BusinessView(View): def get(self,request,*args,**kwargs): return render(request,'business.html') class BusinessJsonView(View): def get(self,request,*args,**kwarg ): response=BaseResponse() try: table_config=[ { 'q':'id', 'title':'业务id', 'display':1, }, { 'q':'name', 'title':'业务名称', 'display':1 }, { 'q':None, 'title':'操作', 'display':1 } ] value_list=[] for items in table_config: print(items['q']) if items['q']: value_list.append(items['q']) print(value_list) result = models.Business.objects.values(*value_list) print(result) data_list = list(result) print(data_list) response.data = { 'table_config':table_config, 'data_list':data_list } except Exception as e: response.data = False response.message = str(e) j=json.dumps(response.__dict__) return HttpResponse(j)