13)django-ORM(连表一对多,外键创建,创建数据,3种查询)

一对多需要使用外键

一:外键创建ForeignKey

  b=models.ForeignKey(to="Business",to_field=("id"))#django会在生成表的时候变为b_id

  to表示和那个表关联,to_field没有和那个字段关联,不写默认是id

  

from django.db import models

# Create your models here.

class Foo(models.Model):
    name=models.CharField(max_length=32)

class Business(models.Model):
    caption=models.CharField(max_length=32)
    code=models.CharField(max_length=32,null=True,default="SA")
    fk=models.ForeignKey(to="Foo",to_field=("id"))#默认会和主键关联

class Host(models.Model):
    nid=models.AutoField(primary_key=True)
    hostname=models.CharField(max_length=32,db_index=True)
    ip=models.GenericIPAddressField(protocol='ipv4',db_index=True)
    port=models.IntegerField()
    b=models.ForeignKey(to="Business",to_field=("id"))

二:一对多数据创建

  一对多数据创建有两种方式

  1)使用对象创建

    

    Host.objects.create(
            hostname="host1",
            ip="1.1.1.1",
            port="22",
            b=Business.objects.filter(id=1).first(),)

  2)直接使用外建字段_id创建

  

    Host.objects.create(
            hostname="host1",
            ip="1.1.1.1",
            port="22",
            b_id=1,) #外键创建时候会自动把字段b建立成b_id字段,可以直接赋值。这种方法好于第一种,原因不需要连表查询,推荐第二种

三:一对多数据查询

  一对多数据查询有两种形式

  1)queryset内容为对象

    Host.objects.filter(nid__gt=0)
    Host.objects.all()等

  

    host_list=Host.objects.all()
    for row in  host_list:
        print(row.b_id)  #直接访问b_id
        print(row.b) #这个是Business对象,所以访问下面的字段
        print(row.b.caption)

     2)查询使用values和values_list指定字段,使用row.b.caption会直接报错。这里可以使用双下线跨表查询.

  3)查询使用values_list指定字段,使用row.b.caption会直接报错。这里可以使用双下线跨表查询.

    注:values返回是字典,values_list返回是元组

    示例如下: views

def host1(request):
    v1=Host.objects.filter(nid__gt=0)

    #v1=Host.objects.filter(nid__gt=0)
   # v1=Host.objects.filter(nid__gt=0).values("nid","hostname","b_id","b.caption") #b.caption不能跨表直接报错
    v2=Host.objects.filter(nid__gt=0).values("nid","hostname","b_id","b__caption") #两个下划线可以实现跨表
    #filter(nid__gt=0).values("nid","hostname","b_id","b__caption")相跨表都用双下划线
    #queryset对象内部为字典
    for row in v2:
        print(row["nid"],row["hostname"],row["b_id"],row["b__caption"])

    v3=Host.objects.filter(nid__gt=0).values_list("nid","hostname","b_id","b__caption")
    return render(request,"host.html",{"v1":v1,"v2":v2,"v3":v3})

  模板代码:

  

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .shade {
            position: fixed;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            background-color: #333333;
            opacity: 0.6;
            z-index: 9;
        }

        .add-mode {
            position: fixed;
            height: 300px;
             400px;
            top: 100px;
            left: 50%;
            margin-left: -200px;
            z-index: 11;
            background-color: white;
        }

        .hide {
            display: none;
        }
    </style>
</head>
<body>
<input type="button" value="增加" id="add_host">

<h1>主机列表(对象)</h1>
<table border="1px">
    <thead>
    <tr>
        <th>序号</th>
        <th>主机名</th>
        <th>主机地址</th>
        <th>端口</th>
        <th>业务线名称</th>

    </tr>
    </thead>
    <tbody>
    {% for row in v1 %}
        <tr host-id="{{ row.nid }}" bid="{{ row.b_id }}">
            <td>{{ forloop.revcounter }}</td>
            <td>{{ row.hostname }}</td>
            <td>{{ row.ip }}</td>
            <td>{{ row.port }}</td>
            <td>{{ row.b.caption }}</td>
        </tr>
    {% endfor %}


    </tbody>
</table>
<h1>主机列表(字典)</h1>
<table border="1px">
    <thead>
    <tr>
        <th>主机名</th>
        <th>主机地址</th>
        <th>端口</th>
        <th>业务线名称</th>
    </tr>
    </thead>
    <tbody>
    {% for row in v2 %}
        <tr host-id="{{ row.nid }}" bid="{{ row.b_id }}">
            <td>{{ row.hostname }}</td>
            <td>{{ row.ip }}</td>
            <td>{{ row.port }}</td>
            <td>{{ row.b__caption }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>
<h1>主机列表(元组)</h1>
<table border="1px">
    <thead>
    <tr>
        <th>主机名</th>
        <th>主机地址</th>
        <th>端口</th>
        <th>业务线名称</th>
    </tr>
    </thead>
    <tbody>
    {% for row in v3 %}
        <tr host-id="{{ row.nid }}" bid="{{ row.b_id }}">
            <td>{{ row.0 }}</td>
            <td>{{ row.1 }}</td>
            <td>{{ row.2 }}</td>
            <td>{{ row.3 }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>
<table border="1px">
    <thead>
    <tr>
        <th>序号</th>
        <th>主机名</th>
        <th>主机地址</th>
        <th>端口</th>
        <th>业务线名称</th>

    </tr>
    </thead>
    <tbody>
    {% for i in v1 %}
        {% for row in v1 %}
            <tr host-id="{{ row.nid }}" bid="{{ row.b_id }}">
                <td>{{ forloop.parentloop }}</td>
                <td>{{ row.hostname }}</td>
                <td>{{ row.ip }}</td>
                <td>{{ row.port }}</td>
                <td>{{ row.b.caption }}</td>
            </tr>
        {% endfor %}
    {% endfor %}


    </tbody>
</table>
<!--模态对话框实现增加主机信息-->
<div class="shade hide"></div>
<div class="add-mode hide">
    <form action="/host" method="post">
        <div class="group">
            <input type="text" name="hostname" placeholder="请输入主机名">
        </div>
        <div class="group">
            <input type="text" name="ip" placeholder="请输入主机IP">
        </div>
        <div class="group">
            <input type="text" name="port" placeholder="请输入主机端口">
        </div>
    <!--绑定businss信息--> <div class="group"> <select name="group_id"> {% for group in v4 %} <option value="{{ group.id }}">{{ group.caption }}</option> {% endfor %} </select> </div> <div class="group"> <input type="submit" value="提交"> <input type="button" value="取消"> </div> </form> </div> <script src="/static/jquery-1.12.4.js"></script> <script> $("#add_host").click( function () { $(".shade,.add-mode").removeClass("hide") } ) </script> </body> </html>
原文地址:https://www.cnblogs.com/lixiang1013/p/7766327.html