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

  • 相关阅读:
    增删改查, SQL语句,注意事项
    形参
    接收前台的GET/POST请求
    数据库能查出数据,但mybatis查询出返回的结果是null
    resultType
    日期和字符串互转、数据库处理日期
    ajax的简单应用
    设置
    深度解密Go语言之unsafe
    golang中,map作为函数参数是如何传递的
  • 原文地址:https://www.cnblogs.com/george92/p/11284829.html
Copyright © 2020-2023  润新知