django 一对多跨表查询多对多
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django 一对多跨表查询多对多相关的知识,希望对你有一定的参考价值。
1.一对多跨表查询获取数据的三种形式:对象、字典、元组
例:有host与business两张表,host与business的id字段关联,business在host表中的对象名是b, 通过查询host表获取的querySet中的b来查询business表。
以下两种方式都是操作host表:
a.以对象的形式跨表查询,查询business表的数据:row.b.caption,row.b.id
b.以字典和元组的形式跨表查询,查询business表的数据,跨表查询的时候要用双下划线 ‘b__id‘,‘b__caption‘, # 这里caption是关联表business的字段
views.py
def host(request): #三种形式的跨表查询(这里有host与business两张表,host与business的id字段关联,business在host表中的对象名是b, # 通过查询host表获取的querySet来查询business表) v1 = models.Host.objects.filter(nid__gt=0) for row in v1: #v1以对象的形式跨表查询row.b.caption, ,row.b.id print(row.nid,row.hostname,row.ip,row.port,row.b.caption,row.b.id) v2 = models.Host.objects.all().values(‘nid‘,‘hostname‘,‘b_id‘,‘b__caption‘,) for row2 in v2: # v2以字典的形式跨表查询,跨表查询(即查询另一个关联表的数据)的时候要用双下划线‘b__caption‘,这里caption是关联表的字段 print(row2) #结果是字典 {‘nid‘: 8, ‘hostname‘: ‘ee‘, ‘b_id‘: 5, ‘b__caption‘: ‘运维‘} print(row2[‘nid‘],row2[‘hostname‘],row2[‘b_id‘],row2[‘b__caption‘]) v3 = models.Host.objects.all().values_list(‘nid‘,‘hostname‘,‘b_id‘,‘b__caption‘) for row3 in v3: # v3以元组的形式跨表查询,跨表查询(即查询另一个关联表的数据)的时候要用双下划线‘b__caption‘,这里caption是关联表的字段 print(row3)#结果是元组 (7, ‘wt‘, 6, ‘开发‘) print(row3[0],row3[1],row3[2],row3[3]) if request.method == ‘GET‘: v1 = models.Host.objects.filter(nid__gt=0) v2 = models.Host.objects.all().values(‘nid‘, ‘hostname‘, ‘b_id‘, ‘b__caption‘, ) v3 = models.Host.objects.all().values_list(‘nid‘, ‘hostname‘, ‘b_id‘, ‘b__caption‘) b_list = models.Business.objects.all() return render(request, ‘host.html‘, {‘v1‘:v1, ‘v2‘:v2, ‘v3‘:v3,‘b_list‘:b_list}) elif request.method == ‘POST‘: h = request.POST.get(‘hostname‘) i = request.POST.get(‘ip‘) p = request.POST.get(‘port‘) b = request.POST.get(‘b_id‘) models.Host.objects.create(hostname=h, ip=i, port=p, b_id=b,) return redirect(‘/host‘)
host.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>对象</h1> <table border="1" style="border-collapse: collapse;"> <thead> <tr> <th>主机名</th> <th>IP</th> <th>端口</th> <th>业务线名称</th> </tr> </thead> <tbody> {% for row in v1 %} <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> <td>{{ row.hostname }}</td> <td>{{ row.ip }}</td> <td>{{ row.port }}</td> {# 查关联表的其他字段caption,这里b是关联表的对象名#} <td>{{ row.b.caption }}</td> </tr> {% endfor %} </tbody> </table> <h1>字典</h1> <table border="1" style="border-collapse: collapse;"> <thead> <tr> <th>主机名</th> <th>业务线名称</th> </tr> </thead> <tbody> {% for row in v2 %} <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> <td>{{ row.hostname }}</td> {# 查关联表的其他字段caption,这里b是关联表的对象名#} <td>{{ row.b__caption }}</td> </tr> {% endfor %} </tbody> </table> <h1>元组</h1> <table border="1" style="border-collapse: collapse;"> <thead> <tr> <th>主机名</th> <th>业务线名称</th> </tr> </thead> <tbody> {% for row in v3 %} <tr hid="{{ row.0 }}" bid="{{ row.2 }}"> <td>{{ row.1 }}</td> <td>{{ row.3 }}</td> {# 查关联表的其他字段caption,这里b是关联表的对象名#} <td>{{ row.b.caption }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
2.模板语言显示序号用forloop,只有for循环里有。
1 <tbody> 2 {% for row in v1 %} 3 <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> 4 <td>{{ forloop.counter }}</td> 5 {#在for循环里才有forloop,forloop.counter自动加序号,从1开始#} 6 {#forloop.counter0自动加序号,从0开始#} 7 {#forloop.revcounter自动加序号,倒数#} 8 <td>{{ row.hostname }}</td> 9 <td>{{ row.ip }}</td> 10 <td>{{ row.port }}</td> 11 <td>{{ row.b.caption }}</td> 12 </tr> 13 {% endfor %} 14 </tbody>
3.后端接收前端多选框、Ctrl多选的数据用method.getlist()
views.py
1 elif request.method == "POST": 2 app_name = request.POST.get(‘app_name‘) 3 host_list = request.POST.getlist(‘host_list‘)#当前端是多选传过来的数据时,用getlist接收,生成列表 4 print(app_name,host_list) 5 6 obj = models.Application.objects.create(name=app_name) 7 obj.r.add(*host_list) #多对多跨表添加数据:*列表名 8 9 return redirect(‘/app‘)
html多选
1 <div class="group"> 2 <select id="host_list" name="host_list" multiple> 3 #multiple是多选的意思 4 {% for op in host_list %} 5 <option value="{{ op.nid }}">{{ op.hostname }}</option> 6 {% endfor %} 7 </select> 8 </div>
4.编辑框的实现和ajax提交表单数据
d20-host.html
{# 下边是编辑框展示#} <div class="shade hide"></div> <div class="add-modal hide"> <form id="add_form" method="POST" action="/host"> <div class="group"> <input id="host" type="text" placeholder="主机名" name="hostname" /> </div> <div class="group"> <input id="ip" type="text" placeholder="IP" name="ip" /> </div> <div class="group"> <input id="port" type="text" placeholder="端口" name="port" /> </div> <div class="group"> <select id="sel" name="b_id"> {% for op in b_list %} {# 生成下拉框#} <option value="{{ op.id }}">{{ op.caption }}</option> {% endfor %} </select> </div> <input type="submit" value="提交" /> <a id="ajax_submit" >悄悄提交</a> <input id="cancel" type="button" value="取消" /> <span id="erro_msg" style="color: red"></span> 提交失败,错误信息显示 </form> $(‘#ajax_submit‘).click(function(){ $.ajax({ url: "/test_ajax", type: ‘POST‘, //data: {‘hostname‘: $(‘#host‘).val(), ‘ip‘: $(‘#ip‘).val(), ‘port‘: $(‘#port‘).val(), ‘b_id‘: $(‘#sel‘).val()}, data: $(‘#add_form‘).serialize(), //serialize()是ajax方法,它能自动找到表单中的name和value数据并提交给后台,跟上边的效果相同 success: function(data){ var obj = JSON.parse(data); if(obj.status){ location.reload();//提交成功自动刷新页面 }else{ $(‘#erro_msg‘).text(obj.error);//提交失败显示错误信息 } } }) });
views.py
后台数据接收
1 elif request.method == "POST": 2 3 h = request.POST.get(‘hostname‘) 4 i = request.POST.get(‘ip‘) 5 p = request.POST.get(‘port‘) 6 b = request.POST.get(‘b_id‘) 7 models.Host.objects.create(hostname=h, 8 ip=i, 9 port=p, 10 b_id=b, 11 ) 12 return redirect(‘/host‘)
以上是关于django 一对多跨表查询多对多的主要内容,如果未能解决你的问题,请参考以下文章