• Django models多表操作



    title: Django models多表操作
    tags: Django

    多表操作

    单独创建第三张表的情况

    推荐使用的是使用values/value_list,selet_related的方式,查询效率高

    建立表

    class Boy(models.Model):
        name = models.CharField(max_length=32)
    
    
    class Girl(models.Model):
        nick = models.CharField(max_length=32)
    
    
    class Love(models.Model):
        b = models.ForeignKey('Boy')
        g = models.ForeignKey('Girl')
    
    

    表建立联合唯一索引unique_together

    class Love(models.Model):
        b = models.ForeignKey('Boy')
        g = models.ForeignKey('Girl')
    
        # 建立联合唯一索引
        class Meta:
            unique_together = [
                ('b','g')
            ]
    
    	"""
        通过第三张表查与男生表有关系的女生
        下面是通过男生表反向查询 使用小写的表明love_set
        """
        # obj = models.Boy.objects.filter(name='钢弹').first() # 这里是对象
        # love_list = obj.love_set.all()
        # for item in love_list:
        #     print(item.g.nick)
    
        """
        通过第三张表正向操作
        """
        # love_list = models.Love.objects.filter(b__name='钢弹')
        # for item in love_list:
        #     print(item.g.nick)
    
        """
        但是上面的情况是for循环多次查询,效率低,
        用values,value_list进行优化,
        values获得是字典,value_list获取的是元组
        """
        # love_list = models.Love.objects.filter(b__name='钢弹').values('g__nick')  # 仅查询一次
        # print(love_list)  # <QuerySet [{'g__nick': '翠花'}, {'g__nick': '英子'}, {'g__nick': '妞子'}]>
        # for item in love_list:
        #     print(item['g__nick'])  # 这是取字典内容
    
        # love_list = models.Love.objects.filter(b__name='钢弹').values_list('g__nick')
        # print(love_list)
        # for item in love_list:
        #     print(item[0])  # 取元组中的内容 取第一个
    
        """
        使用select_related 进行优化 查询到的是一个对象
        """
        # love_list = models.Love.objects.filter(b__name='钢弹').select_related('g') # 直接写外键原来的名字
        # print(love_list)
        # for obj in love_list:
        #     print(obj.g.nick)  # 是通过对象查
    

    使用ManyToManyField 创建表

    使用ManyToManyField,Django会自动生成第三张表,但是没有相应的类,是不能直接操作django自动生成的表的。但是可以通过Boy表关联的m间接的进行操作。

    生成的第三张表示boy_m

    class Boy(models.Model):
        name = models.CharField(max_length=32)
        m = models.ManyToManyField("Girl")  # 里面写的是要关联的表
    
    
    class Girl(models.Model):
        nick = models.CharField(max_length=32)
    

    对第三张表进行增删改

     	obj = models.Boy.objects.filter(name='钢弹').first()
        print(obj.id,obj.name)
    	
    	"""
    	增加操作
    	"""
        # obj.m.add(2)  # 增加一个 最终增加的是g_id-->  1 2
        # obj.m.add(1,2,3)  # 增加多个
        # obj.m.add(*[4,])  # 使用列表进行接收
    
    	"""
    	删除操作
    	"""
        # obj.m.remove(2)  
        # obj.m.remove(1,2,3) 
        # obj.m.remove(*[4,]) 
    

    通过ManyToMany查询的,关键是通过all查询的是girl的对象

     	obj = models.Boy.objects.filter(name='钢弹').first()
        print(obj.id,obj.name)
        girl_list = obj.m.all() # 查询的时候Django自动获得是girl对象
        print(girl_list)
        for item in girl_list:
            print(item.nick)  # 从对象获取
    

    还可以继续进行过滤,filter内部的字段是Girl内部的

     girl_list = obj.m.all().filter(nick='翠花') # 查询的时候Django自动获得是girl对象
        for item in girl_list:
            print(item.nick)  # 从对象获取
    

    修改内容

    set是重置

    obj.m.set([1,2])
    

    清空clear是清空与之关联的全部

    obj.m.clear()
    

    ManyToMany的反向操作

        """
        ManyToMany的反向操作
        小写的表名_set.all()
        通过Girl取Boy
        """
        obj = models.Girl.objects.filter(nick='翠花').first()
        boy_list = obj.boy_set.all()
        print(boy_list)
        for item in boy_list:
            print(item.name)  # 从对象获取
    ``
    
    
    ### 混合使用
    
    ManyToMany的缺陷是只能自动创建3列字段,不能再进行扩展。所以用到了下面的混合使用
    
    
    不影响第三张表的使用,第三张表还是通过类进行增加删除
    
    通过ManyToMany增加的是**查询和清空**的功能
    
    
    
    #### 创建
    
    **关键是 through  through_fields**,through指定的是自己创建的第三张表,
    
    through_fields指定的是第三张表中的字段
    
    这样就指定了自己创建第三张表,不通过ManyToMany创建
    
    ```python
    class Boy(models.Model):
        name = models.CharField(max_length=32)
        m = models.ManyToManyField("Girl",through='Love',through_fields=('b','g'))
        # m = models.ManyToManyField("Girl")
    
    
    class Girl(models.Model):
        nick = models.CharField(max_length=32)
    
    
    class Love(models.Model):
        b = models.ForeignKey('Boy')
        g = models.ForeignKey('Girl')
    
        # 建立联合唯一索引
        class Meta:
            unique_together = [
                ('b','g')
            ]
    
    

    使用

    obj.m.clear()
    obj.m.all()
    

    中间遇到的错误,强制删除了m表

    ValueError: Cannot alter field app01.Boy.m into app01.Boy.m - they are not compatible types (you cannot alter to or from M2M fields, or add o
    r remove through= on M2M fields)
    
  • 相关阅读:
    Centos7 定时任务
    Linux启动配置文件和运行等级runlevel
    Linux 网卡命名规则
    将博客搬至CSDN
    Lua调用C++动态链接库.so
    使用shell脚本执行批量mongosh语句
    TCP和UDP详解
    经受时延的确认(Delay ACK)
    18张图带你了解衡量网络性能的四大指标:带宽、时延、抖动、丢包
    TCP学习
  • 原文地址:https://www.cnblogs.com/Python666/p/7148028.html
Copyright © 2020-2023  润新知