ORM之多对多操作
ORM之多对多操作
创建两张单表Boy和Girl,和一张多对多连表Love:
class Boy(models.Model): name = models.CharField(max_length=255) class Girl(models.Model): nick = models.CharField(max_length=255) class Love(models.Model): b = models.ForeignKey("Boy") g = models.ForeignKey("Girl")
那么如何在查询的时候用到Love表的关联呐?
#方式一: obj = Boy.objects.filter(name = "george").first() love_list = obj.love_set.all() #通过obj反向连表love去拿到所有的b和g for row in love_list: print(row.g.nick) #这样就拿到了在love表中所有与george有关系的人啦 #方式二: love_list = models.Love.objects.filter(b__name="george") for row in love_list: print(row.g.nick) #方式三: love_list = models.Love.objects.filter(b__name="george").values("g__nick") for item in love_list: print(item["g__nick"]) #方法四: love_list = models.Love.objects.filter(b__name="george").select_related("g") for obj in love_list: print(obj.g.nick)
ManyToManyField:
可以在没有外键关联的第三张的前提下,创建第三张表。用ManyToManyField的话,那么第三张表也就不用写了。
如果Django自动生成第三张表,那么我们是无法直接操作第三张表的。他会在库里新建一个 “表名_m” 的表。来存储两张表ManyToManyField的关系。
class Boy(models.Model): """ ManyToManyField不会新建一列,而是会键一个表 如果想使boy和girl关联,那么ManyToManyField写在哪里都可以 """ name = models.CharField(max_length=255) m = models.ManyToManyField("Girl") class Girl(models.Model): nick = models.CharField(max_length=255) # m = models.ManyToManyField("Boy")
如何要给第三张表插入数据,改如何做呐?在ORM操作中,要操作第三张表是要通过操作那个表的类来实现数据操作的。但是ManyToManyField是没有实质的第三张表的类的,所以要如何操作呢?
和第三张唯一有关系的,就是Boy的m字段,所以只能从m下手。也就只能通过Boy对象渗透到m。
添加m表的数据:
obj = models.Boy.objects.filter(name="george").first() print(obj.id,obj.name) obj.m.add(3) #操作m的添加操作,这样会获取george的id,并将Boy关联的Girl的id为3的与其捆绑成一对。 obj.m.add(2,4) obj.m.add(*[5,]) # 也可以添加列表
数据库结果:
删除m表的数据:
obj.m.remove(1) #用 remove 的方式删除,删除的参数是以Girl 删除1,是girl_id的1,然后与girl_id=1的数据行就删除了 obj.m.remove(2,4) obj.m.remove(*[5,])
修改m表的数据:
操作:
obj.m.set([1,]) # 修改是用set是实现,但是set是重置的,比如我们的m拿到的是george,id也是george的id # 这里的set([1,]) 是将和george有关的id都删除,从新创建一天数据,并将girl_id=1 的数据与其捆绑
set的重置的结果:
clear操作:
obj = models.Boy.objects.filter(name="george").first() obj.m.clear() # 把所以和george有关的girl的id,在m表中全部清除。
但是这样的效果不好,不灵活。比如我只想更改一条与george有关的数据,结果这样就全变了,所以我们可以自己写:
obj = models.Boy.objects.filter(name="george").first() girl_list = obj.m.all() #girl_list 是girl的所有的对象 但是因为是通过Boy的获取的,所以这个Girl_list的数据是只和george相关的数据 girl_list1 = obj.m.filter(nick="sihui") #这个filter因为是已经通过了筛选之后的girl数据, # 所以这里的filter就相当于是 obj.girl.object.filter() 所以filter的参数是girl表的字段 print(girl_list1) #这个girl_list1 的结果就是一个数据
查询m表的数据:
既是girl表中没有ManyToManyField,也是可以通过小写表名_set 的方式获取girl的数据。
obj = models.Girl.objects.filter(nick="hhh").first() print(obj.id,obj.nick) v = obj.boy_set.all() print(v)
和girl表的hhh有关系的两个boy数据。
如何是同时有ManyToManyField和多对多的关系表该如何:
在有ManyToManyField和多对多的表时,这里会创建四张表,但是如何写了ManyToManyField而又不想使其生成表,就在写ManyToManyField的Boy表里加through,表示和那张表做关联,through_fields是指定那些字段做关联。
class Boy(models.Model): """ ManyToManyField不会新建一列,而是会键一个表 如果想使boy和girl关联,那么ManyToManyField写在哪里都可以 """ name = models.CharField(max_length=255) m = models.ManyToManyField("Girl",through="Love",through_fields("b","g",)) #通过through连接Love表,并通过through_fields来指定那些字段做关联。 class Girl(models.Model): nick = models.CharField(max_length=255) # m = models.ManyToManyField("Boy") class Love(models.Model): b = models.ForeignKey("Boy") g = models.ForeignKey("Girl") class Meta: unique_together = [ ("b","g"), ]
在view里操作:
obj = models.Boy.objects.filter(name="george").first()
obj.m.clear() #在这种环境下,只有clear是可以用的。还有查询操作,是add和remove是不可用的。
obj = models.Boy.objects.filter(name="george").first() v = obj.m.all() #拿的是Girl的对象 print(v)
----------- END ------------