Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】

上一篇:Django之Model操作之一对多外键(ForeignKey)正反调用【ORM篇五】 点击跳转
目录篇:Django之model操作ORM目录篇 点击跳转
下一篇:Django之Model操作之单表及跨表(双下划线)的3种不同方式获取数据【ORM篇七】点击跳转

目录

  • ManyToMany
  •     多对多介绍
  •     Django提供的三种多对多方式
  •     具体示例
  •         1.自动创建多对多关联(django自动维护第三张表)
  •         2.手动创建多对多关联(手动维护第三章表)
  •         3.自动+手动(手动维护第三章表)

ManyToMany

    多对多介绍

在多对多关系中,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提供的三种多对多方式

而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

        1.自动创建多对多关联(django自动维护第三张表)

表类

    路径: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表

Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】_第1张图片

    B表

Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】_第2张图片

    M2M表

Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】_第3张图片

 

具体操作(正反操作)     

路径: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

        2.手动创建多对多关联(手动维护第三章表)

表类

    路径: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表

Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】_第4张图片

    B表

Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】_第5张图片

    M2M表

Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】_第6张图片

具体操作(四种方式)

路径: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()


    

 

        3.自动+手动(手动维护第三章表)

表类

    路径: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表

Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】_第7张图片

    B表

Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】_第8张图片

   M2M表

Django之Model操作之多对多(ManyToMany)正反调用【ORM篇六】_第9张图片

 

具体操作(四种方式)

路径: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篇七】点击跳转​​​​​​​

你可能感兴趣的:(Django)