Django默认ORM(六):多对多(M2M)操作
1.创建关系表
class Boy(models.Model): name = models.CharField(max_length=16) class Girl(models.Model): nick = models.CharField(max_length=16) #创建多对多的关系表 class Love(models.Model): b = models.ForeignKey("Boy") g = models.ForeignKey("Girl") #除外键外,创建其他的约束关系(联合索引or联合唯一索引)注意语法结构! class Meta: #定义关系类,固定写法 #创建联合唯一索引 unique_together=[ #关系类型 = [("别名1","别名2"),] #列表,元素是元组 ("b","g"), ], #创建联合索引 index_together=[ ("c","d"), ] 操作: #批量增加数据 objs = [ models.Boy(name="小张"), models.Boy(name="小王"), models.Boy(name="小李"), models.Boy(name="小宋"), ] models.Boy.objects.bulk_create(objs,5) obs = [ models.Girl(nick="小红"), models.Girl(nick="小黄"), models.Girl(nick="小绿"), models.Girl(nick="小紫"), ] models.Girl.objects.bulk_create(obs,5) objs = [ models.Love(b_id=1,g_id=1), models.Love(b_id=1,g_id=2), models.Love(b_id=1,g_id=3), models.Love(b_id=2,g_id=1), models.Love(b_id=2,g_id=2), ] models.Love.objects.bulk_create(objs,5) #连表操作,查找与小张有过关联的女生 #字典类型的数据 love_list = models.Love.objects.filter(b__name="小张").values("g__nick") for item in love_list: print(item["g__nick"]) #对象类型的数据 love_lists = models.Love.objects.filter(b__name="小张").select_related("g") for obj in love_lists: print(obj.g.nick)
2.通过django自带功能ManyToManyField,完成多对多关系的关联 (任意表添加,但局限性太大)
- 创建表的过程中,不再写关系表,而是对某个表中添加关联信息,django会自动创建一个以主键为准的信息关联表 (表格式:项目名_小写表名_自定义名)。 特别注意:表内的数据结构是固定的,如果除了建立多对多的关系外还需要记录其他的数据, 则该表无法插入新的列,以至于无法完成你的要求! - 类内定义的方式: 自定义名 = models.ManyToManyField("要关联的类名") 1)创建表: class Boy(models.Model): name = models.CharField(max_length=16) m = models.ManyToManyField("Girl") #多对多,django会自动创建一个新表,用以存放多对多关系。 class Girl(models.Model): nick = models.CharField(max_length=16) 2)表操作: #哪个表建立的关系,就先从这个表操作。 # 先获取boy对象 obj = models.Boy.objects.filter(name="小张").first() #通过多对多的名,对第三张关系表进行操作! # 添加数据 obj.m.add(1) #添加一个数据 obj.m.add(2,3) #添加多个数据 obj.m.add(*[4,]) #以列表形式添加 #删除 obj.m.remove(1) obj.m.remove(2,3) obj.m.remove(*[4,]) #重置 #把当前对象的数据清空,再重新写入 obj.m.set([1,]) #查询全部 -->已经完成了跨表 跨到了女生表 q = obj.m.all() print(q) #查看拿到的数据类型及所属对象,发现全是gril表的对象 for item in q: print(item.nick) #获取每个对象的名称 #过滤查找 girl_list = obj.m.values("nick").filter(nick="小红").first() print(girl_list) #反向跨表,通过女生找到约会过的男生 obj = models.Girl.objects.values("id","nick","boy__name").filter(nick="小红") print(obj) #清表 把关系表内的数据全部清除 obj.m.clear()
3.自定义表与django自带功能ManyToManyField合用(杂交):
1)创建表: class Boy(models.Model): name = models.CharField(max_length=16) m = models.ManyToManyField("Girl",through="Love",through_fields=("b","g",)) #指定通过哪个表连接,用哪几列进行关联! class Girl(models.Model): nick = models.CharField(max_length=16) #创建多对多的关系表 class Love(models.Model): b = models.ForeignKey("Boy") g = models.ForeignKey("Girl") #除外键外,其他的约束关系(联合索引or联合唯一索引) class Meta: #创建联合唯一索引 unique_together=[ ("b","g"), ], 2)操作:有约束 可以通过自定义的关系表进行增删改查操作; 但是通过django自带的关系有会有约束,只能查询或是清表,其他操作会报错。 查 | 清表 obj.m.clear() 可以 v = obj.m.all() print(v)