Django之ORM连表操作
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)多对多:在某表中创建一行数据是,有一个可以多选的下拉框。
例如:创建用户信息,需要为用户指定多个爱好。
(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张表,变成一张表! )
想象有第二张表,关联自己表中的行
相关推荐:《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多对多查询:
女士表:
男生表:
男女关系表
多对跨表操作
#获取方少伟有染的女孩 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(' 要关联的表') 自动生成)
由于 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
多对多自关联特性:
ManyToManyField生成的第三张表
Django 提供一个“信号分发器”,允许解耦的应用在框架的其它地方发生操作时会被通知到。也就是说在特定事件发生时,可以发送一个信号去通知注册了这个信号的一个或者多个回调,在回调里进行逻辑处理。Django内置了 ...