上一篇:Django之Model操作之一对多外键(ForeignKey)正反调用【ORM篇五】 点击跳转
目录篇:Django之model操作ORM目录篇 点击跳转
下一篇:Django之Model操作之单表及跨表(双下划线)的3种不同方式获取数据【ORM篇七】点击跳转
目录
在多对多关系中,A 表中的一行可以匹配 B 表中的多行,反之亦然。要创建这种关系,需要定义第三个表,称为结合表,它的主键由 A 表和 B 表的外部键组成
简单解释:
一个人可以扮演多个不同的角色,一个角色同样可以给多个不同的人扮演,目前有两张表:人表、角色表。人表
id 姓名 年龄 性别 1 burgess 15 男 2 小强 18 男
角色表
id 角色名 1 至尊宝 2 独孤求败
第三张表:
id 人_id 角色_id 1 1(burgess) 1(至尊宝) 2 1(burgess) 2(独孤求败) 3 2(小强) 3(至尊宝)
这样我们通过第三张表就可以知道burgess和小强分别演过哪些角色
同理我们通过第三张表就可以知道至尊宝该角色分别哪些人演过
如果你1对多外键关联(ForeignKey)弄懂了,那么多对多对于你来说就非常的简单,其实就是在第三张表弄两个字段分别进想外键关联两个表
而django的多对多有3种方式可以选择
1.通过m2m字段自动创建了第三张表(django自动维护第三张表)
2.创建第三张表(需要手动维护该表)
3.通过m2m字段指定手动表(需要手动维护该表)注意:
1.根据多对多字段进行系统自动生成的第三张表,admin会帮你生成下拉框,系统自动维护第三张表(根据django提供的格式进行操作第3战表)
2.手动创建第三张表,admin是不会生成下拉框的,自己维护第三张表(第3张表进行手动操作)
3.自动+手动,admin是不会生成下拉框,自己维护第三张表(第3张表进行手动操作,django提供格式只允许查和清除功能)
实战Django之Model操作之多对多(ManyToMany)正反调用 https://blog.csdn.net/Burgess_zheng/article/details/86594225
表类
路径:project/app/models.py
from django.db import models class A(models.Model): name = models.CharField(max_length=10) class B(models.Model): name = models.CharField(max_length=10) m2m = models.ManyToManyField("A",related_name='bn')
表数据
A表
B表
M2M表
具体操作(正反操作)
路径:project/app/views.py
from app import models def models_handle(request): A_obj = models.A.objects.filter()#获取全部或者匹配的列表形式 A_obj = models.A.objects.all()#获取全部列表 A_obj = models.A.objects.get(id=1)#一个queryset对象 #如果匹配不到,或者匹配的超出一个报错 A_obj = models.A.objects.first() #获取该表第一个queryset对象 B_obj = models.B.objects.first() ########B正向调取(通过B表的多对多字段调用)######### for obj in B_obj.m2m.all(): print(obj.name) #得到红1 红2 #Django创建的多对多表增删改查(正向操作) A_obj = models.A.objects.first() #数据对象(A表第一行数据) B_obj = models.B.objects.first() #数据对象(B表第一行数据) B_obj.m2m.add(1) #B_obj对象本身进行关联A表的指定id数据(第三张表自动维护增加) B_obj.m2m.add(2,3,4) #B_obj对象本身进行关联A表的N个指定id数据(第三张表自动维护增加) B_obj.m2m.add(*[2,3,4]) #B_obj对象本身进行关联A表的N个指定id数据(第三张表自动维护增加) B_obj.m2m.remove(1) #移除该B_obj对象所关联的A表的指定id数据(第三张表自动维护移除) B_obj.m2m.remove(2,3) #移除该B_obj对象所关联的A表的N个指定id数据(第三张表自动维护移除) B_obj.m2m.remove(*[2,3]) #移除该B_obj对象所关联的A表的N个指定id数据(第三张表自动维护移除) B_obj.m2m.clear(*[2,3]) #清除掉该B_obj对象所有关联A表的id数据(第三张表自动维护移除) B_obj.m2m.set(*[2,3]) #重置该B_obj对象的关联的A表指定N个id数据(第三张表自动维护重置) A_obj.m2m.all() #查看该B_obj对象所关联的A表的所有数据 A_obj.m2m.filter(xx='xx') #查看该B_obj对象所关联的A表的指定数据 ########A反向调取(通过多对多字段设置的related_name进行反向调用)######## for obj in A_obj.bn.all(): obj.name #得到强1 强2 #Django创建的多对多表增删改查(反向操作) A_obj = models.A.objects.first() #数据对象(A表第一行数据) A_obj.bn.add(1) #A_obj对象本身进行关联B表的指定id数据(第三张表自动维护增加) A_obj.bn.add(2,3,4) #A_obj对象本身进行关联B表的N个指定id数据(第三张表自动维护增加) A_obj.bn.add(*[2,3,4]) #A_obj对象本身进行关联B表的N个指定id数据(第三张表自动维护增加) A_obj.bn.remove(1) #移除该A_obj对象所关联的B表的指定id数据(第三张表自动维护移除) A_obj.bn.remove(2,3) #移除该A_obj对象所关联的B表的N个指定id数据(第三张表自动维护移除) A_obj.bn.remove(*[2,3]) #移除该A_obj对象所关联的B表的N个指定id数据(第三张表自动维护移除) A_obj.bn.clear(*[2,3]) #清除掉该A_obj对象所有关联B表的id数据(第三张表自动维护移除) A_obj.bn.set(*[2,3]) #重置该A_obj对象的关联的B表指定N个id数据(第三张表自动维护重置) A_obj.bn.all() #查看该A_obj对象所关联的B表的N个数据 A_obj.bn.filter(xx=xx) #查看该A_obj数据所关联的B表的指定数据 #插入:如果数据表创建的时候多对多字段没有设置related_name参数(“多对多表名小写“ + “_set“) #for obj in A_obj.b_set.all(): # obj.name
表类
路径:project/app/models.py
from django.db import models class A(models.Model): name = models.CharField(max_length=10) class B(models.Model): name = models.CharField(max_length=10) class M2M(models.Model): a_obj = models.ForeignKey("A",related_name="an",on_delete=None) b_obj = models.ForeignKey("B",related_name="bn",on_delete=None)
表数据
A表
B表
M2M表
具体操作(四种方式)
路径:project/app/views.py
from app import models def models_handle(request): A_obj = models.A.objects.filter()#获取全部或者匹配的列表形式 A_obj = models.A.objects.all()#获取全部列表 A_obj = models.A.objects.get(id=1)#一个queryset对象 #如果匹配不到,或者匹配的超出一个报错 A_obj = models.A.objects.first() #获取该表第一个queryset对象 B_obj = models.B.objects.first() m2m_obj= models.M2M.objects #####获取A表指定数据对象的所有关联的B表数据 #方式1(通过多对多字段设置的related_name进行反向调用) A_obj = models.A.objects.first() B_obj = models.B.objects.first() m2m_obj= models.M2M.objects for m2m_obj in A_obj.an.all(): m2m_obj.b_obj.name #插入:(如果数据表创建时候没有使用related_name参数(”多对多表名小写” + “_set”) #for m2m_obj in A_obj.m2m_set.all(): #m2m_obj.b_obj.name #方式2(通过M2M表字段,字段值,字段双下划线+关联表字段进行匹配指定A_obj对象的对应信息,最终得到了该A_obj对象所关联B_obj对象的m2m本表对象,然后通过该m2m对象调用自身关联B表的外键字段) A_obj = models.A.objects.filter(id=1).first() m2m_obj=models.M2M.objects.filter(a_obj=A_obj) #对象方式 m2m_obj=models.M2M.objects.filter(a_obj_id=A_obj.id) #本表字段值方式 m2m_obj=models.M2M.objects.filter(a_obj__id=A_obj.id) #双下划线+关联表(A表)的字段方式 m2m_obj=models.M2M.objects.filter(a_obj__name=A_obj.name) #双下划线+关联表(A表)的字段方式 for m2m_obj in m2m_obj: m2m_obj.b_obj.name #方式3(通过多对多字段设置的related_name进行反向调用) A_obj = models.A.objects.filter(id=1).first() b_list_obj=models.B.objects.filter(bn__a_obj=A_obj) #m2m表对象方式 b_list_obj=models.B.objects.filter(bn__a_obj_id=A_obj.id) #m2m表字段值方式 for obj in b_list_obj: obj.name #插入:(如果数据表创建时候没有使用related_name参数(”多对多表名小写”) #b_list_obj=models.B.objects.filter(m2m__a_obj=A_obj) #m2m对象方式 #b_list_obj=models.B.objects.filter(m2m__a_obj_id=A_obj.id) #m2m字段值方式 #方式4(通过多对多字段设置的related_name进行反向调用) A_obj = models.A.objects.filter(id=1).first() b_list_obj = models.B.objects.filter(bn__a_obj__name=A_obj.name) #双下划线+关联表(A表)字段方式 b_list_obj = models.B.objects.filter(bn __a_obj__id=A_obj.id) #双下划线+关联表(A表)字段方式 for obj in b_list_obj: obj.name #插入:(如果数据表创建时候没有使用related_name参数(”多对多表名小写”) #b_list_obj = models.B.objects.filter(m2m__a_obj__name=A_obj.name) #双下划线+关联表(A表)字段方式 #b_list_obj = models.B.objects.filter(m2m__a_obj__id=A_obj.id) #####获取B表指定数据对象的所有关联的A表数据(方式和上面一样道理的,就是颠倒而已,就不在重复) #####M2M表(第三张表)的手动操作增删改查 #增 models.M2M.objects.create(b_obj=B_obj,a_obj=A_obj) #这种创建是要把对象(实例instance)赋值进去 models.M2M.objects.create(a_obj_id=3,b_obj_id=3) #这种创建才是用了自身表的id字段进行创建 #改 models.M2M.objects.filter(id=5).update(a_obj=A_obj,b_obj=B_obj) #这种更新(修改)把对象(实例instance)赋值进去 models.M2M.objects.filter(id=4).update(a_obj_id=3,b_obj_id=3) #这种更新(修改)才是用了自身表的id字段进行更新 #删 models.M2M.objects.filter(id=5).delete() #改(另外save形态的) m2m_obj_save = models.M2M.objects.filter(id=4).first() m2m_obj_save.a_obj = A_obj m2m_obj_save.b_obj = B_obj m2m_obj_save.save()
表类
路径:project/app/models.py
from django.db import models class A(models.Model): name = models.CharField(max_length=10) class B(models.Model): name = models.CharField(max_length=10) m2m = models.ManyToManyField("A",through="M2M",through_fields=("b_obj","a_obj")) class M2M(models.Model): a_obj = models.ForeignKey("A",related_name="an",on_delete=None) b_obj = models.ForeignKey("B",related_name="bn",on_delete=None)
表数据
A表
B表
M2M表
具体操作(四种方式)
路径:project/app/views.py
获取A表某条数据的所有关联的B表数据(和上面手动创建操作一样)
获取B表某条数据的所有关联的A表数据(和上面手动创建操作一样)
M2M表(第三张表)的手动操作(和上面手动创建操作一样)唯一的区别就是B对象可以通过自身的m2m字段进行有限操作(使用B表的m2m字段操作(有限制只允许:查、清))
from app import models def models_handle(request): A_obj = models.A.objects.first() B_obj = models.B.objects.first() m2m_obj= models.M2M.objects #B_obj是B表的id1该数据,该数据关联了A表的id1 和id3 B_obj.m2m.all() B_obj.m2m.clear() #清除B表该id1的数据的所有关联A表的数据
上一篇:Django之Model操作之一对多外键(ForeignKey)正反调用【ORM篇五】 点击跳转
目录篇:Django之model操作ORM目录篇 点击跳转
下一篇:Django之Model操作之单表及跨表(双下划线)的3种不同方式获取数据【ORM篇七】点击跳转