首页 > 代码库 > django(3) 一对多跨表查询、多对多

django(3) 一对多跨表查询、多对多

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)
View Code

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>
View Code

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(3) 一对多跨表查询、多对多