代码改变世界

djanjo ORM 一对多、多对多

2016-04-23 11:34  echo_小白  阅读(469)  评论(0编辑  收藏  举报

一、表操作之一对多

定义表结构:定义了UserType、两张表UserInfo,如下:

from django.db import models

class UserType(models.Model):
    caption = models.CharField(max_length=32)

class UserInfo(models.Model):
    user_type = models.ForeignKey(UserType)# user_type对象中封装id,caption
    username = models.CharField(max_length=32)
    age = models.IntegerField()

向表中添加数据:

UserType表如数据如下:
1    CTO
2    CEO
3    COO


UserInfo表中数据如下:
1    alex01    88    1
6    alex02    77    1
7    alex03    66    2
8    alex04    55    3

 

正向查询:

        要求: 查找user_type为CEO的有哪些人

        代码如下:

def user_info(request):
    #正向查找
    result = models.UserInfo.objects.filter(user_type__caption='CEO')
    for item in result:
        print item.username,item.age,item.user_type.caption

运行后结果如下,user_type为ceo的就一人,alex03

image

 

反向查询:

通过user_type查找,UserType可用的搜索条件有:id,captin,userinfo,其中userinfo(userinfo_set)为django自动生成的对像,对应UserInfo表,我们可用于查询。

查询条件userinfo应用示例:

def user_info(request): #反向查: line = models.UserType.objects.get(id=1) print line.id print line.caption print line.userinfo_set.all()

print line.userinfo_set.filter(username='alex02')

#获取用户类型是cto有且用户名为alex02的记录

# line.userinfo_set.filter(username='alex02') 等价于==》models.UserInfo.objects.filter(user_type=line)

 

查询需求:#获取某个有是什么 用户类型?当前用户类型下有多少人?

def user_info(request):

    #获取某个有是什么 用户类型?当前用户类型下有多少人?
    user_type_obj = models.UserType.objects.get(userinfo__username='alex02')#alex02的用户类型
    print user_type_obj.caption #类型名
    print user_type_obj.userinfo_set.all().count() #这个用户类型下有多少人

执行结果:用户类型为cto的确如下2条

image

 

一对多操作总结:

一对多
    1、创建
         对象(obj=model)
         _id(obj_id)
    2、查找
        正向
            查询:filter,  __跨表  对像__跨表的字段
            获取值:line.对像.跨表的字段
        反向
            查询:表名_set(filter 跨表,自动创建表名相同的对像__跨表的字段)
            获取值:line.自动创建表名相同的对像_set.filter()|all()

 

二、表操作之多对多

 

1.django自动实现的多对多

两个表的多对多关系,借助第3张表来完成的,双向的一对多就是多对多

多对多关系:

   
主机表:
主机id    主机名    端口
1               host1     80
2               host2    90
3               host3    100


用户表:
用户Id    用户名    手机
1               user1    xxxx
2               user2    xxxx
3               user3    xxxx

例如:用户user1同时管理hosts1 host2两台主机,用第3张表来实现就简单很多
关系表:
用户id   主机id       #这里就表示了user1同理管理两台主机的关系
1        1
1        2

 

django的多对多,第3张关系表由django自动创建

多对多表结构:定义了Host、HostAdmin两张表,如下:

class Host(models.Model):
    hostname = models.CharField(max_length=32)
    port = models.IntegerField()

class HostAdmin(models.Model):
    username = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    host = models.ManyToManyField(Host)

表加添加记录:

def user_info(request):
  #添加基础数据   models.Host.objects.create(hostname='c1',port='80')
     models.Host.objects.create(hostname='c2',port='81')
     models.Host.objects.create(hostname='c3',port='82')
    
     models.HostAdmin.objects.create(username='root',email='1@live.com')
     models.HostAdmin.objects.create(username='dali',email='2@live.com')
     models.HostAdmin.objects.create(username='haojie',email='3@live.com')

    #正向添加host字段记录
    #给root分配两个主机的管理权限
    #1 获取root用户
     admin_obj = models.HostAdmin.objects.get(username='root')
    #2获取指定的主机
     host_list = models.Host.objects.filter(id__lt=3)
    #3 装两个主机添加到表中
     admin_obj.host.add(*host_list)

    #反向添加host字段记录
     host_obj = models.Host.objects.get(id=3)#在host表中获取id为3的主录
     admin_list = models.HostAdmin.objects.filter(id__gt=1)#在admin表中获取id大于1的记录有2条
     host_obj.hostadmin_set.add(*admin_list)#为主机添加两个管理员

 

添加完后,表中记录如下:

host表:

1    c1    80
2    c2    81
3    c3    82

 

hostadmin表:

1    root    1@live.com
2    dali    2@live.com
3    haojie    3@live.com

 

django自动生成的关系表:

1    1    1
2    1    2
3    2    3
4    3    3

 

 

2.自定义实现多对多

表结构定义:

###################################自定义多对多关系表
class Host1(models.Model):
    hostname = models.CharField(max_length=32)
    port = models.IntegerField()

class HostAdmin1(models.Model):
    username = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    host = models.ManyToManyField(Host1, through='HostRelation') #自定义关系表,指定关系表名

class HostRelation(models.Model):#自定义的关系表
    c1 = models.ForeignKey(Host1)
    c2 = models.ForeignKey(HostAdmin1)

关系表中如何添加数据:

def user_info(request):
    #方法一
    models.HostRelation.objects.create(
        c1=models.Host1.objects.get(id=1),
        c2=models.HostAdmin1.objects.get(id=2),
    )
    
    #方法二:优点,做了0次数据库查询,1次插入
    models.HostRelation.objects.create(
        c1_id = 1,
        c2_id = 2,
    )

查看关系表中,数据如下:

1    1    2

 

自定义多对多的查询

def user_info(request): #查询

#第一种 #正向查

admin_obj = models.HostAdmin1.objects.all(id=1)#获取id为1的对像 for item in admin_obj: item.host1.all()#获取host1表中的相关记录 #反向查 host_obj = models.Host1.objects.get(id=1) #在hosts1表中获取id为1的记录 host_obj.hostadmin1_set.all()#通过id为1的记录查找hostadmin1表中的管理员 #第二种:直接操作关系表,不存在正反查询 #relation_list = models.HostRelation.objects.all()#获取所有记录 relation_list= models.HostRelation.objects.filter(c2__username='user01') #查找user01管理的所有主机 for item in relation_list:#循环关系表,每一个item就是一个关系(对像)

        print item.c1.hostname
print item.c2.username
  

结果如下:

image

 

 

 

多对多查询总结:

1、自动生成关系表
        间接的方式获取关系表:
                    1、正, 一行数对象.M2M字段
                    2、反, 一行数对象.表名_set
    2、自定义关系表(推荐)
                     只对关系表操作