文章 > Django > Django之ORM连表操作

Django之ORM连表操作

头像

爱喝马黛茶的安东尼

2019-07-02 10:48:522489浏览 · 0收藏 · 0评论

ORM连表操作

我们在学习django中的orm的时候,我们可以把一对多,多对多,分为正向和反向查找两种方式。

正向查找:ForeignKey在 UserInfo表中,如果从UserInfo表开始向其他的表进行查询,这个就是正向操作,反之如果从UserType表去查询其他的表这个就是反向操作。

(1)一对多:models.ForeignKey(其他表)

(2)多对多:models.ManyToManyField(其他表)

(3)一对一:models.OneToOneField(其他表)

正向连表操作总结:

所谓正、反向连表操作的认定无非是Foreign_Key字段在哪张表决定的,

Foreign_Key字段在哪张表就可以哪张表使用Foreign_Key字段连表,反之没有Foreign_Key字段就使用与其关联的小写表名;

1对多:对象.外键.关联表字段,values(外键字段__关联表字段)

多对多:外键字段.all()

反向连表操作总结:

通过value、value_list、fifter 方式反向跨表:小写表名__关联表字段

通过对象的形式反向跨表:小写表面_set().all()

前端ajax需要携带的参数 

根据前端参数,返回不同数据库结果

应用场景:

(1)一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)

例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。

(2)多对多:在某表中创建一行数据是,有一个可以多选的下拉框。

例如:创建用户信息,需要为用户指定多个爱好。

a.png

(3)一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了。

例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据。

1对多

如果A表的1条记录对应B表中N条记录成立,两表之间就是1对多关系;在1对多关系中 A表就是主表,B表为子表,ForeignKey字段就建在子表;

如果B表的1条记录也对应A表中N条记录,两表之间就是双向1对多关系,也称为多对多关系;

在orm中设置如果 A表设置了外键字段user=models.ForeignKey('UserType')到B表(注意外键表名加引号)

就意味着 写在写A表的B表主键, (一列),代表B表的多个(一行)称为1对多,

查询

总结:利用orm获取 数据库表中多个数据

获取到的数据类型本质上都是 queryset类型,

类似于列表,

内部有3种表现形式(对象,字典,列表)

modle.表名.objects.all()

modle.表名.objects.values()

modle.表名.objects.values()

跨表

正操作

所以表间只要有外键关系就可以一直点下去。

所以可以通过obj.外键.B表的列表跨表操作(注意!!orm连表操作必须选拿单个对象,不像SQL中直接表和表join就可以了)

print(obj.cls.title)

foreignkey字段在那个表里,那个表里一个"空格"代表那个表的多个(一行)

class UserGroup(models.Model):
            """
            部门 3
            """
            title = models.CharField(max_length=32)
        class UserInfo(models.Model):
            """
            员工4
            """
            nid = models.BigAutoField(primary_key=True)
            user = models.CharField(max_length=32)
            password = models.CharField(max_length=64)
            age = models.IntegerField(default=1)
            # ug_id 1
            ug = models.ForeignKey("UserGroup",null=True)

1. 在取得时候跨表

q = UserInfo.objects.all().first()

q.ug.title

2. 在查的时候就跨表了 

UserInfo.objects.values('nid','ug_id') 

UserInfo.objects.values('nid','ug_id','ug__title')    #注意正向连表是  外键__外键列 反向是小写的表名

3. UserInfo.objects.values_list('nid','ug_id','ug__title')

反向连表:

反向操作无非2种方式:

(1)通过对象的形式反向跨表:小写表面_set().all()

(2)通过value和value_list方式反向跨表:小写表名__字段

1. 小写的表名_set 得到有外键关系的对象

obj = UserGroup.objects.all().first()

result = obj.userinfo_set.all() [userinfo对象,userinfo对象,]

2. 小写的表名 得到有外键关系的列 #因为使用values取值取得是字典的不是对象,所以需要 小写表名(外键表)__

v = UserGroup.objects.values('id','title') 

v = UserGroup.objects.values('id','title','小写的表名称') 

v = UserGroup.objects.values('id','title','小写的表名称__age') 

3. 小写的表名 得到有外键关系的列

v = UserGroup.objects.values_list('id','title') 

v = UserGroup.objects.values_list('id','title','小写的表名称') 

v = UserGroup.objects.values_list('id','title','小写的表名称__age')

1对多自关联( 由原来的2张表,变成一张表! )

想象有第二张表,关联自己表中的行

s.png

d.png

相关推荐:《Python视频教程

代码

    class Comment(models.Model):
                """
                评论表
                """
                news_id = models.IntegerField()            # 新闻ID
                content = models.CharField(max_length=32)  # 评论内容
                user = models.CharField(max_length=32)     # 评论者
                reply = models.ForeignKey('Comment',null=True,blank=True,related_name='xxxx') #回复ID

多对多:

1、自己写第3张关系表

ORM多对多查询:

女士表:

a.png

男生表:

s.png

男女关系表

d.png

多对跨表操作

#获取方少伟有染的女孩
    obj=models.Boy.objects.filter(name='方少伟').first()
    obj_list=obj.love_set.all()
    for row in obj_list:
        print(row.g.nike)
    # 获取和苍井空有染的男孩
    obj=models.Girl.objects.filter(nike='苍井空').first()
    user_list=obj.love_set.all()
    for row in  user_list:
        print(row.b.name)

多对多关系表   数据查找思路

(1)找到该对象

(2)通过该对象 反向操作 找到第三张关系表

(3)通过第三张关系表 正向操作 找到 和该对象有关系对象

总结

只要对象1和对象2 中间有关系表建立了关系; 对象1反向操作 到关系表 ,关系表正向操作到对象2,反之亦然。

2、第3张关系表不用写(m=models.ManyToManyField(' 要关联的表') 自动生成)

1562035302215495.png

由于 DjangoORM中一个类名对应一张表,要想操作表就modles.类直接操作那张表,但使用ManyToManyField字段生成 “第三张”关系表怎么操作它呢?

答案:通过单个objd对象 间接操作

class Boy(models.Model):
    name = models.CharField(max_length=32)
    m = models.ManyToManyField('Girl',through="Love",through_fields=('b','g',))
class Girl(models.Model):
    nick = models.CharField(max_length=32)
    m = models.ManyToManyField('Boy')

正向操作: obj.m.all()

obj = models.Boy.objects.filter(name='方少伟').first()
    print(obj.id,obj.name)
    obj.m.add(2)
    obj.m.add(2,4)
    obj.m.add(*[1,])
    obj.m.remove(1)
    obj.m.remove(2,3)
    obj.m.remove(*[4,])
    obj.m.set([1,])
    q = obj.m.all()
    # [Girl对象]
    print(q)
    obj = models.Boy.objects.filter(name='方少伟').first()
    girl_list = obj.m.all()
    obj = models.Boy.objects.filter(name='方少伟').first()
    girl_list = obj.m.all()
    girl_list = obj.m.filter(nick='小鱼')
    print(girl_list)
    obj = models.Boy.objects.filter(name='方少伟').first()
    obj.m.clear()

反向操作 :obj.小写的表名_set

多对多和外键跨表一样都是 小写的表名_set

3、既自定义第三张关系表 也使用ManyToManyField('Boy')字段(杂交类型)

ManyToManyField()字段创建第3张关系表,可以使用字段跨表查询,但无法直接操作第3张表,

自建第3表关系表可以直接操作,但无法通过字段 查询,我们可以把他们结合起来使用;

作用:

(1)既可以使用字段跨表查询,也可以直接操作第3张关系表

(2)obj.m.all() 只有查询和清空方法

外键反向查找别名(方便反向查找)

在写ForeignKey字段的时候,如果想要在反向查找时不使用默认的 小写的表名_set,就在定义这个字段的时间加related参数!

related_name、related_query_name 字段=什么别名 反向查找时就使用什么别名!

反向查找:

设置了related_query_name 反向查找时就是obj.别名_set.all()保留了_set

related_query_name

related_name

反向查找:

设置了relatedname就是 反向查找时就说 obj.别名.all()  

多对多自关联(由原来的3张表,变成只有2张表)

把两张表通过 choices字段合并为一张表

‘第三张关系表’ 使用models.ManyToManyField('Userinfo')生成

特性:

obj = models.UserInfo.objects.filter(id=1).first()  获取对象

(1)查询第三张关系表前面那一列:obj.m

select xx from xx where from_userinfo_id = 1

(2)查询第三张关系表后面那一列:obj.userinfo_set

select xx from xx where to_userinfo_id = 1

多对多自关联特性:

x.png

ManyToManyField生成的第三张表

cc.png

关注

关注公众号,随时随地在线学习

本教程部分素材来源于网络,版权问题联系站长!