django的get方法是从数据库的取得一个匹配的结果,返回一个对象,如果记录不存在的话,它会报错。
django的filter方法是从数据库的取得匹配的结果,返回一个对象列表,如果记录不存在的话,它会返回[]。

orm 详解

ORM的一对多:

我们在设计表结构的时候什么时候使用一对多呢?

比如我们在建立用户的时候有个菜单让我们选择用户类型的时候,使用一对多!!

1、一对多的正向查找:

正向查:ForeignKey在UserInfo表里,如果根据UserInfo这张表去查询这两张关联的表的合起来的内容就是正向查

反向查:ForeignKey不在UserType里,如果根据UserType这张表去查询这两张关联的表的合起来的内容就是反向查

正向查-demo1--查询所有用户为COO 的用户

在django中外键就相当于简单的使用__连表,在外键那个对象中封装了user_type表中的所有字段

我们要查询所有用户为CEO的用户,我们是不是的根据UserType这张表去查,如果是跨表查询使用“双下划线” + 属性

1
2
3
4
5
6
7
from app01 import models
def index(req):
    ret = models.UserInfo.objects.filter(user_type__caption='COO')
    print(ret)
    for item in ret:
        print(item,item.username,item.age,item.user_type.caption)
    return HttpResponse("OK")

查询结果:

orm 详解

反向查询:--

我们可以根据下面的命令,取出一个用户组,那么对于这个用户组他有多少个用户呢?

1
models.UserType.objects.get(id=1)
1
2
3
4
5
6
7
8
9
10
11
obj=models.UserType.objects.get(id=1)
    obj.caption====得到在UserType表中id为1对应的caption
    obj.id======得到在UserType表中id为1
    obj.userinfo_set  #理解为一种能力,可以获取所有当前这个用户类型的用户/或者这个用户类型的多个用户
    obj.userinfo_set.all() #获取所有用户类型为COO的用户
    obj.userinfo_set.filter(username='tim') #获取用户类型为COO的并且用户为tim的用户
 
    '''
    这.userinfo_set.相当于什么?它相当于  models.UserInfo.objects.filter(user_type=obj)
 
    '''

反向查询实例:查询COO用户下的所有的用户名

1
2
3
ret = models.UserType.objects.filter(caption='COO').values('userinfo__username')
   for item in ret:
       print(item,type(item))

方法二、

1
2
3
4
ret = models.UserType.objects.filter(caption='COO').first()
 
    for item in  ret.userinfo_set.all():
        print(item.username)

总结:

  正向查找:

    filter(跨表的时候,应该是对象__跨表的字段)

    获取这个值的时候,拿到了一行数据的时候 line.对象.跨表的字段

  反向查找:

    filter(关联这个表的表明) 自动创建和表明相同的对象,通过这个对象__跨表的字段

    line.自动创建和表明相同的对象_set.方法

orm 详解

ORM多对多  系统生成第三张表:

多对多和一对多没有任何关系

models.py

1
2
3
4
5
6
7
8
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')

当我们在host表里和hostadmin表里添加数据时和第三章关系表没有任何关系,当我们这样去建立表时,第三张表里面的列就已经固定了,分别是这两个表的id

给主机表添加数据:

1
2
3
4
5
6
7
8
9
10
11
def index(req):
    #主机数据
    models.Host.objects.create(hostname='host1.test.com', port=80)
    models.Host.objects.create(hostname='host2.test.com', port=80)
    models.Host.objects.create(hostname='host3.test.com', port=80)
    models.Host.objects.create(hostname='host4.test.com', port=80)
    #用户数据
    models.HostAdmin.objects.create(username='alex', email='alex@qq.com')
    models.HostAdmin.objects.create(username='mosson', email='mosson@qq.com')
    models.HostAdmin.objects.create(username='aliven', email='aliven@qq.com')
    models.HostAdmin.objects.create(username='wusir', email='wusir@qq.com')

数据中的效果:

orm 详解

orm 详解

空的关系表

orm 详解

多对多正向、反向添加数据

orm 详解

正向添加数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def index(request):
 
    #正向添加数据
 
    #找到用户dali这个
    admin_obj = models.HostAdmin.objects.get(username='dali')
    #找到主机
    host_list = models.Host.objects.filter(id__lt=3)
    #通过找到的dali的对象.add去添加数据
    admin_obj.host.add(*host_list)
    '''
    admin_obj 通过大力这个对象.add 去操作的主机,
    大力的ID为 2 主机ID为:(1,2)
    那就会生成这样的表:
    #2 1
    #2 2
    '''
    return HttpResponse('OK')

反向添加数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def index(request):
 
    #反向添加数据
    #获取主机
    host_obj = models.Host.objects.get(id=3)
    #获取用户列表
    admin_list = models.HostAdmin.objects.filter(id__gt=1)
    #和一对多一样的道理
    host_obj.hostadmin_set.add(*admin_list)
    #host_obj = 3   管理员ID = 2 3 4
    #3 2
    #3 3
    #3 4   
    return HttpResponse('OK')

ORM 多对多 自定义 第三张表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class HostInfo(models.Model):
    hostname = models.CharField(max_length=32)
    port = models.IntegerField()
 
class UserMap(models.Model):
    username = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
 
    #through告诉Django用那张表做关联
    host = models.ManyToManyField(HostInfo , through='HostRelation')
 
class HostRelation(models.Model):
    host = models.ForeignKey('HostInfo')
    user = models.ForeignKey('UserMap')
 
    '''
    并且这里我们可以添加多个关系,比如在加一个字段
    usertype = models.ForeignKey('UserType')
    或者增加一个普通字段
    status = models.CharField(max_length=32)
    '''

现在咱们自己创建了第三张表了。现在我们已经会了两种方式创建第三张表了,当我们使用自定义创建的第三张表的时候,在去添加数据的时候!

就不能使用第一种方式对象添加了!

现在我们有第三张表了这个对象了,我们就不需要管另外两张表了,直接添加就行了! 0 0 !

添加主机和用户--

1
2
3
4
5
6
7
8
9
10
11
def index(req):
 
    models.HostInfo.objects.create(hostname='alex.test.com', port=80)
    models.HostInfo.objects.create(hostname='seven.test.com', port=80)
    models.HostInfo.objects.create(hostname='mosson.test.com', port=80)
 
    models.UserMap.objects.create(username='alex', email='alex@qq.com')
    models.UserMap.objects.create(username='seven', email='seven@qq.com')
    models.UserMap.objects.create(username='mosson', email='mosson@qq.com')
 
    return HttpResponse('ok')

将数据插入到第三张表中---办法1:

插入单条数据

1
2
3
4
5
6
def index(request):
    models.HostRelation.objects.create(
        user = models.UserMap.objects.get(id=1),
        host = models.HostInfo.objects.get(id=1)
    )
    return HttpResponse('OK')

多对多两种方式对比和查询

orm 详解

查询--方法一:

第一种方式都是基于表中的对象去找到第三张表! 通过间接的方式找到这张表的句柄!

1
2
3
4
5
6
#正向查
admin_obj = models.HostAdmin.objects.get(id=1)
admin_obj.host.all()
#反相差
host_obj = models.Host.objects.get(id=1)
host_obj.hostadmin_set.all()

查询--方法二:

用第二种方法就没有正向和反向这么一说了,直接查即可!

1
2
3
4
relation_list = models.HostRelation.objects.all()
for item in relation_list:  #每一个item就是一个关系
    print (item.user.username)
    print( item.host.hostname)
1
2
3
4
relation_list = models.HostRelation.objects.filter(user__username='mosson')
    for item in relation_list:  #每一个item就是一个关系
        print( item.user.username)
        print (item.host.hostname)

通过第二种方式可以把所有的关系都找到,第一种方式可以把所有的关系表都找到吗?

第一种方式只能找到某一个人管理的机器,不能把有的对应关系找到!

select_related的作用:

1
2
3
4
5
6
7
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()

select_related的作用,他就是用来优化查询的,没有他也可以,用它主要是用来优化ForeignKey

1
2
3
4
5
6
7
def index(request):
    ret = models.UserInfo.objects.all()
    #咱们看下他执行的什么SQL语句
    print( ret.query)
'''
SELECT "app01_userinfo"."id", "app01_userinfo"."user_type_id", "app01_userinfo"."username", "app01_userinfo"."age" FROM "app01_userinfo"
'''

加上select_related是什么样子的

网站名称:orm详解
当前路径:http://tjjierui.cn/article/ijchgo.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP