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 ------------

原文地址:https://www.cnblogs.com/george92/p/11284829.html